sql >> Databasteknik >  >> NoSQL >> MongoDB

MongoDB Geospacial frågesfärer som överlappar en enda punkt

Det skulle vara trevligare om du kunde använda ett GeoJSON-objekt för att representera platsen, men för närvarande är typer som stöds är faktiskt begränsade så en "Cirkel"-typ som skulle vara idealisk stöds inte.

Det närmaste du kan göra är en "Polygon" som approximerar en cirkel, men det här är förmodligen lite för mycket arbete att konstruera bara för detta frågeändamål. Den andra måste göra detta och sedan använda $geoIntersects är att resultaten inte kommer att "sorteras" efter avståndet från frågepunkten. Det verkar vara motsatsen till syftet med att hitta "närmast pizza" till ursprungsplatsen.

Lyckligtvis finns det en $geoNear operation läggs till i aggregeringsramverket från och med MongoDB 2.4 och senare. Det som är bra här är att det tillåter "projicering" av ett avståndsfält i resultaten. Detta låter dig sedan göra den logiska filtreringen på servern till de punkter som är "inom radie"-begränsningen till avståndet från utgångspunkten. Det tillåter också sortering på servern.

Men du kommer fortfarande att behöva ändra ditt schema för att stödja indexet

db.places.insert({
    "name": "Pizza Hut",
    "location": { 
        "type": "Point",
        "coordinates": [
            151.00211262702942,
            -33.81696995135973
        ]
    },
    "radius": 20
})

db.places.ensureIndex({ "location": "2dsphere" })

Och för aggregeringsfrågan:

db.places.aggregate([

    // Query and project distance
    { "$geoNear": {
        "near": { 
            "type": "Point",
            "coordinates": [ 
                150.92094898223877,
                -33.77654333272719
            ]
        },
        "distanceField": "distance",
        "distanceMultiplier": 0.001,
        "maxDistance": 100000,
        "spherical": true
    }},

    // Calculate if distance is within delivery sphere
    { "$project": {
         "name": 1,
         "location": 1,
         "radius": 1,
         "distance": 1,
         "within": { "$gt": [ "$radius", "$distance" ] }
    }},

    // Filter any false results
    { "$match": { "within": true } },

    // Sort by shortest distance from origin
    { "$sort": { "distance": -1 } }
])

I grund och botten säger detta,

Det finns andra alternativ som du kan skicka till $geoNear för att förfina resultatet, samt returnera mer än standardvärdena 100 resultat om det behövs och i princip skicka andra alternativ för att fråga, såsom en "typ" eller "namn" eller vilken annan information du har på dokumentet.




  1. Redis-transaktioner och långvariga Lua-skript

  2. Flerfältsfrågor på Redis med Redis Spring

  3. Express Node.JS - Tar emot Redis-återuppringning, utför löften

  4. Hur utför man en NOT IN-fråga i mongodb utan att använda $nin?