Mongodb:通过子文档字段(GeoJSON)查询文档

时间:2019-02-17 23:04:58

标签: mongodb mongoose mongodb-query geojson mongoose-schema

我的数据库模型中有三个文档架构:pointSchema(仅是GeoJSON Point定义),PlaceSchema(这是一个真实的地方,如夜总会)和EventSchema(将存储与聚会和节日等事件相关的数据)。

但是我遇到了一些问题。我需要根据他的位置查询事件文档,但是,该位置数据存储在与事件有关系的子文档中。

以下是我的架构定义:

const pointSchema = new mongoose.Schema({
  type: {
    type: String,
    enum: ['Point'],
    required: true
  },
  coordinates: {
    type: [Number],
    required: true
  }
});

const PlaceSchema = new mongoose.Schema(
  {
    name: {
      type: String,
      required: true
    },
    location: {
      type: pointSchema,
      required: true
    }
  },
  {
    versionKey: false,
    timestamps: true
  }
);
PlaceSchema.index({
  name: 'text',
  location: "2dsphere"
});

const EventSchema = new mongoose.Schema(
  {
    name: {
      type: String,
      required: true
    },
    place: {
      type: mongoose.SchemaTypes.ObjectId,
      ref: 'Place'
    }
  },
  {
    versionKey: false,
    timestamps: true
  }
)
EventSchema.index({
  name: 'text'
})

我可以使用以下方法过滤位置文档:

db.Places.find({ 
    location: {
        $geoWithin: { 
            $centerSphere: [ 
                [ -28.824342, -49.218433 ],
                100 / 6378.1 
            ] 
        } 
    }
})

但是,当我尝试过滤事件时,我不能做同样的事情。我已经尝试过这样的查询:

db.Events.find({ 
    "place.location": {
        $geoWithin: { 
            $centerSphere: [ 
                [ -28.824342, -49.218433 ],
                100 / 6378.1 
            ] 
        } 
    }
})

,但是该解决方案不起作用。有人可以帮助我吗?

谢谢。

1 个答案:

答案 0 :(得分:0)

由于place文档中的event只是ObjectId,因此您有2个选择之一

  1. 多个发现
let places = db.Places.find({ 
   location: {
       $geoWithin: { 
           $centerSphere: [ 
               [ -28.824342, -49.218433 ],
               100 / 6378.1 
           ] 
       } 
   }
}, { _id:1 }) // get the places _ids

let events = db.events.find({
   place: { $in: places.map(p => p._id) }
}) // get events that has the places _ids

  1. 聚合
const stages = [
{ $geoNear: {
   near: { type: "Point", coordinates: [ -28.824342, -49.218433 ] },
   distanceField: "distance",
   spherical: true,
   maxDistance: 100 / 6378.1
} },
{ $lookup: {
   from: 'events',
   localField: '_id',
   foreignField: 'place',
   as: 'events'
} }
];

let result = db.places.aggregate(stages);