我有一个包含这样的文档的集合:
{
"_id" : "cysMrqjootq6YS6WP",
“profile” : {
……
"deliveryDistance” : 20,
"address" : {
"loc" : {
"type" : "Point",
"coordinates" : [
—2.120361,
52.536273
]
} }
}
}
我有一个GeoJSON点,如:
var referencePoint= {
"type" : "Point",
"coordinates" : [
—2.120361,
52.536273
]
}
我正在使用Meteor.js,Node.js和MongoDB。我想创建一个查询,其中此点的maxDistance是每个文档到我的集合中的deliveryDistance属性。
如果maxDistance是固定值,则查询为:
myCollection.find({
“profile.address.loc":{
"$nearSphere": {
"$geometry": referencePoint,
"$maxDistance": 20000 //for 20Kms
}
}
})
但事实并非如此。对于每个文档,maxDistance必须是'profile.deliveryDistance'的值。如何在此查询中将文档中的此值用作maxDistance?可能吗?如果没有,还有其他想法吗?
答案 0 :(得分:3)
您无法在.find()
查询中引用文档的现有属性,并且至少不在$near
或$nearSphere
操作中。
相反,这里的方法是使用聚合框架和$geoNear
。这允许您计算与查询点的距离,然后比较是否属于" deliveryDistance"在文件中。
所以对于meteor,你可能最好安装meteorhacks aggregate包,然后做这样的事情:
Meteor.publish("aggResults",function(referencePoint) {
var self = this;
var results = myCollection.aggregate([
{ "$geoNear": {
"near": referencePoint,
"distanceField": "distance",
"spherical": true
}},
{ "$redact": {
"$cond": {
"if": { "$lt": [ "$distance", "$profile.deliveryDistance" ] },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
]);
_.each(results,function(result) {
self.added("client_collection_name",result._id, {
"profile": result.profile,
"distance": result.distance
});
});
self.ready();
})
如果您的MongoDB服务器小于2.6版(并且地理空间查询必须至少为2.4),那么您将使用$project
和$match
来代替$redact
来过滤输出不属于" deliveryDistance":
var results = myCollection.aggregate([
{ "$geoNear": {
"near": referencePoint,
"distanceField": "distance",
"spherical": true
}},
{ "$project": {
"profile": 1,
"distance": 1,
"within": { "$lt": [ "$distance", "$profile.distance" ] }
}},
{ "$match": { "within": true } }
]);
但这是基本情况,你给服务器提供工具来计算距离比较,然后返回任何这些文件。
汇总输出的包装实际上取决于您在应用程序中使用数据的重要性。这只是将输出放入客户端可寻址集合的一个示例。
当然,您也可以深入了解驱动程序内部,将.aggregate()
称为shown here,但它可能不如使用上述流星程序包灵活。