sql >> Database teknologi >  >> NoSQL >> MongoDB

Mongoose aggregering med geonear

Du kan bruge aggregeringsrammen til dette, og der er ingen reel straf, da operationerne i det væsentlige er de samme.

Men mens mangusten .find() metoden har i øjeblikket et problem med $nearSphere operatør, som er ækvivalent, kan du altid få fat i rå node-driverforbindelsesobjektet og udføre din forespørgsel.

Du behøver ikke engang at smide ting som "befolkning", hvis du er parat til at implementere lidt håndtering.

Her er mine testdata:

{ 
    "_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")
}

Og den grundlæggende kode til at håndtere dette:

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 ) );
      });

    });

  }
);

Så der fik du brug af både spring og grænse operationer på markøren, fik en markør returneret og behandlede endda dokumenterne tilbage til "Mongoose Documents", så du kan kalde funktioner som .populate() på dem.

Jeg forventer det aktuelle problem med $nearSphere skal dog rettes relativt snart.

Eller brug aggregat i stedet:

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 ) );
    });

  }
);

Hvor du kan gøre de samme ting såsom at bruge .populate() . Begge tilfælde returnerer resultater som dette med det "udfyldte" felt matchet:

{
    "_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
        ]
    }
}

Selvfølgelig, hvis du ikke har brug for den sfæriske geometriberegning, er $near operatoren fungerer perfekt med Mongoose-implementeringen af ​​.find()



  1. REACT anmodning om hentning af indlæg

  2. Redis vs Service Bus til pub/sub-scenarie

  3. C# + MongoDB - ObjectId uden at bruge MongoDB DataTypes/Attributes

  4. Nedsætte værdien i mongodb