sql >> Databasteknik >  >> NoSQL >> MongoDB

Mongooseaggregation med geonear

Du kan använda aggregeringsramverket för detta och det finns ingen verklig påföljd eftersom operationerna i huvudsak är desamma.

Men medan mangusten .find() metod har för närvarande ett problem med $nearSphere operatör som är likvärdig, kan du alltid ta tag i anslutningsobjektet för rånoddrivrutinen och göra din fråga.

Du behöver inte ens slänga saker som "befolkning" om du är beredd att genomföra lite hantering.

Här är mina 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")
}

Och den grundläggande koden för att hantera detta:

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å där fick du användning av både hopp och gräns operationer på markören, fick en markör att returnera och till och med bearbetade dokumenten tillbaka till "Mongoose Documents" så att du kan anropa funktioner som .populate() på dem.

Jag förväntar mig det aktuella problemet med $nearSphere ska fixas relativt snart dock.

Eller använd aggregat istället:

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

  }
);

Där du kan göra samma saker som att använda .populate() . Båda fallen ger resultat som detta med det "fyllda" fältet matchat:

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

Naturligtvis om du inte behöver beräkningen av sfärisk geometri är $nära operatorn fungerar perfekt med Mongoose-implementeringen av .find()



  1. $push och $set i samma MongoDB-uppdatering

  2. hur man kontrollerar från en drivrutin, om mongoDB-servern körs

  3. Hur EXPIRE HSET barnnyckeln i redis?

  4. Hur beräknar jag ruttavstånd mellan många GeoJSON-punkter i MongoDB?