sql >> Databáze >  >> NoSQL >> MongoDB

Agregace mongoose s geonear

K tomu můžete použít agregační rámec a neexistuje žádný skutečný postih, protože operace jsou v podstatě stejné.

Ale zatímco mongoose .find() metoda má v současnosti problém s $nearSphere operátora, který je ekvivalentní, můžete vždy uchopit nezpracovaný objekt připojení ovladače uzlu a provést dotaz.

Nemusíte ani vyhazovat věci, jako je „populace“, pokud jste připraveni implementovat trochu manipulace.

Zde jsou moje testovací data:

{ 
    "_id" : "P1",
    "amenity" : "restaurant", 
    "shape" : { 
        "type" : "Point", 
        "coordinates" : [ 2, 2 ] 
    }
}
{ 
    "_id" : "P3",
    "amenity" : "police",
    "shape" : { 
        "type" : "Point", 
        "coordinates" : [ 4, 2 ]
    }
}
{ 
    "_id" : "P4",
    "amenity" : "police",
    "shape" : {
        "type" : "Point",
        "coordinates" : [ 4, 4 ]
    }
}
{ 
    "_id" : "P2",
    "amenity" : "restaurant",
    "shape" : { 
        "type" : "Point",
        "coordinates" : [ 2, 4 ]
    }, 
    "info" : ObjectId("539b90543249ff8d18e863fb")
}

A základní kód, jak to zvládnout:

var mongoose = require('mongoose'),
    async = require('async'),
    Schema = mongoose.Schema;


mongoose.connect('mongodb://localhost');

var infoSchema = new Schema({
  "description": String
});

var shapeSchema = new Schema({
  "_id": String,
  "amenity": String,
  "shape": {
    "type": { "type": String },
    "coordinates": []
  },
  "info": { "type": Schema.Types.ObjectId, "ref": "Info" }
});

var Shape = mongoose.model( "Shape", shapeSchema );
var Info = mongoose.model( "Info", infoSchema );


Shape.collection.find(
  {
    "shape": {
      "$nearSphere": {
        "$geometry": {
          "type": "Point",
          "coordinates": [ 2, 4 ]
        }
      }
    }
  },
  {
    "skip": 0, "limit": 2
  },
  function(err,cursor) {

    cursor.toArray(function(err,shapes) {

      Shape.populate( shapes, { path: "info" }, function(err,docs) {
        if (err) throw err;

        console.log( JSON.stringify( docs, undefined, 4 ) );
      });

    });

  }
);

Takže tady máte použití obou přeskočení a limit operace s kurzorem, vrácený kurzor a dokonce zpracování dokumentů zpět do "Mongoose Documents", takže můžete volat funkce jako .populate() na nich.

Očekával bych aktuální problém s $nearSphere bude však poměrně brzy opraveno.

Nebo místo toho použijte agregaci:

Shape.aggregate(
  [
    { "$geoNear": {
        "near": {
          "type": "Point",
          "coordinates": [ 2, 4 ]
        },
        "spherical": true,
        "distanceField": "dis"
    }},
    { "$skip": 0 },
    { "$limit": 2 }

  ],
  function(err,shapes) {
    if (err) throw err;
    //console.log( shapes );

    shapes = shapes.map(function(x) {
      delete x.dis;
      return new Shape( x );
    });

    Shape.populate( shapes, { path: "info" }, function(err,docs) {
      if (err) throw err;

      console.log( JSON.stringify( docs, undefined, 4 ) );
    });

  }
);

Kde můžete dělat stejné věci, jako je použití .populate() . Oba případy vrátí výsledky, jako je tento, se shodným polem "vyplněné":

{
    "_id": "P2",
    "amenity": "restaurant",
    "info": {
        "_id": "539b90543249ff8d18e863fb",
        "description": "Jamies Restaurant",
        "__v": 0
    },
    "shape": {
        "type": "Point",
        "coordinates": [
            2,
            4
        ]
    }
},
{
    "info": null,
    "_id": "P4",
    "amenity": "police",
    "shape": {
        "type": "Point",
        "coordinates": [
            4,
            4
        ]
    }
}

Samozřejmě, pokud nepotřebujete výpočet sférické geometrie, pak $near Operátor funguje perfektně s implementací Mongoose .find()



  1. Poskytovatel ASP.NET SessionState podporovaný Redis

  2. MISCONF Redis je nakonfigurován pro ukládání snímků RDB

  3. Nejlepší postup pro upgrade Redis pomocí Sentinelů?

  4. Odkazování na jiné dokumenty pomocí řetězce spíše než ObjectId