7

Używam modułu node-geoip i wykonuję kwerendę agregacji. Schemat przeciwko której jestem wykonywania kwerendy wygląda następująco:MongoDB/Mongoose - Agregacja z geoNear i podokumentami

var mongoose = require('mongoose'); 
require('./location.js'); 

module.exports = mongoose.model('Region',{ 
    attr1: Number, 
    attr2: String, 
    attr3: String, 
    locations:[mongoose.model('Location').schema] 
}); 

i

var mongoose = require('mongoose'); 

module.exports = mongoose.model('Location',{ 
    attr1: Number, 
    latlong: { type: [Number], index: '2d' }, 
}); 

trzeba wykonać operację $ geoNear w zapytaniu agregacji, ale biegnę na kilka problemów . Po pierwsze, tutaj jest moja metoda agregacji:

var region = require('../models/region'); 

var geo = geoip.lookup(req.ip); 

region.aggregate([ 
    {$unwind: "$locations"}, 
    {$project: { 
     attr1 : 1, 
     attr2 : 1, 
     locations : 1, 
     lower : {"$cond" : [{$lt: [ '$locations.attr1', '$attr1']}, 1, 0]} 
    }}, 
    { 
     $geoNear: { 
     near: { type:"Point", '$locations.latlong': geo.ll }, 
     maxDistance: 40000, 
     distanceField: "dist.calculated" 
     } 
    }, 
    { $sort: { 'locations.attr1': -1 } }, 
    {$match : {lower : 1}}, 
    { $limit: 1 } 
], function(err,f){...}); 

Pierwszym problemem Dostaję jest to, że najwyraźniej geoNear musi być w pierwszym etapie rurociągu: exception: $geoNear is only allowed as the first pipeline stage. Moje pytanie brzmi: czy mogę przeprowadzić wyszukiwanie geoNear w subdokumentach bez ich rozwijania? Jeśli tak to jak?

Drugi komunikat o błędzie, który dostaję, to errmsg: \"exception: 'near' field must be point\". Co to znaczy i co oznacza dla mojego kodu? Próbowałem za pomocą near jak:

near: { type:"Point", '$locations.latlong': geo.ll }, 
+0

Czy próbowałeś zdefiniować "blisko" jako punkt? Na przykład; w pobliżu: [długość geograficzna, szerokość geograficzna], – cdagli

+0

Indeksy na tablicach są wielostronicowe. '$ GeoNear' powinno działać poprawnie na macierzy - porządek powinien być najbliższy punktowi w każdym dokumencie. Drugi błąd mówi, że nie używasz '$ geoNear' z właściwą składnią. Sprawdź ['$ geoNear'] (http://docs.mongodb.org/manual/reference/operator/aggregation/geoNear/), w szczególności przykłady na dole. – wdberkeley

+0

@wdberkeley Dzięki za odpowiedź. Kiedy mówisz "zamawianie powinno być najbliższym punktem w każdym dokumencie", co masz na myśli? Naprawdę nie rozumiem, co to oznacza dla mojego kodu? Czy to oznacza, że ​​mogę przenieść '$ geoNear' na pierwszy etap przed rozwinięciem' $ locations'? – Jordan

Odpowiedz

4

pierwszy Disclaimer: Nie jestem Node/Mongoose ekspert więc mam nadzieję, że można tłumaczyć ogólnych formatów node/Mongoose.

Dla błędu:

errmsg: "exception: 'near' field must be point" 

Przez '2d' indeks ten nie może być punktem GeoJson a zamiast tego musi być "Legacy pary współrzędnych". np

{ 
    "$geoNear": { 
    "near": geo.ll, 
    "maxDistance": 40000, 
    "distanceField": "dist.calculated" 
    } 
} 

Jeśli chcesz użyć GeoJSON trzeba będzie użyć indeksu „2dsphere”.

Po tej zmianie zapytanie $ geoNear będzie działać z tablicą punktów w zapytaniu. Przykładem w powłoce:

> db.test.createIndex({ "locations": "2d" }) 
> db.test.insert({ "locations": [ [1, 2], [10, 20] ] }); 
> db.test.insert({ "locations": [ [100, 100], [180, 180] ] }); 
> db.test.aggregate([{ 
    "$geoNear": { 
    "near": [10, 10], 
    "maxDistance": 40000, 
    "distanceField": "dist.calculated", 
    num: 1 
    } 
}]); 
{ 
    "result": [{ 
    "_id": ObjectId("552aaf7478dd9c25a3472a2a"), 
    "locations": [ 
     [ 
     1, 
     2 
     ], 
     [ 
     10, 
     20 
     ] 
    ], 
    "dist": { 
     "calculated": 10 
    } 
    }], 
    "ok": 1 
} 

Zauważ, że można dostać tylko jeden dystans dla każdego dokumentu (najbliższy punkt), która nie jest semantycznie samo jak robi to odpoczynek i następnie określaniu odległości do każdego punktu. Nie mogę być pewien, czy to jest ważne dla twojego przypadku użycia.