MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Agrégation de mangoustes avec geonear

Vous pouvez utiliser le cadre d'agrégation pour cela et il n'y a pas de réelle pénalité car les opérations sont essentiellement les mêmes.

Mais tandis que la mangouste .find() a actuellement un problème avec le $nearSphere qui est équivalent, vous pouvez toujours saisir l'objet de connexion du pilote de nœud brut et effectuer votre requête.

Vous n'avez même pas besoin de jeter des choses comme "population" si vous êtes prêt à mettre en place un peu de manipulation.

Voici mes données de test :

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

Et le code de base pour gérer cela :

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

    });

  }
);

Donc là, vous avez utilisé à la fois le saut et limite opérations sur le curseur, a renvoyé un curseur et a même traité les documents dans "Mongoose Documents" afin que vous puissiez appeler des fonctions comme .populate() sur eux.

Je m'attendrais au problème actuel avec $nearSphere à corriger assez rapidement cependant.

Ou en utilisant un agrégat à la place :

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

  }
);

Où vous pouvez faire les mêmes choses comme utiliser .populate() . Les deux cas renvoient des résultats comme celui-ci avec le champ "rempli" correspondant :

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

Bien sûr, si vous n'avez pas besoin du calcul de géométrie sphérique, alors le $near L'opérateur fonctionne parfaitement avec l'implémentation Mongoose de .find()