[英]How to remove data from mongodb collection using nodejs and mongoose
[英]How to find data of nearest location from mongodb collection using mongoose?
我正在尋找branchId [Array]最近的分支的列表,例如:[109,110,115]
// My Schema
var BranchSchema = new Schema({
branchId : { type : Schema.Types.ObjectId },
branchName : { type : String },
branchAddress : {
Address:{ type : String, required : false},
City :{ type : String, required : false },
Country : { type : String , required : false}
},
loc: {
type: [Number], // [<longitude>, <latitude>]
index: '2d' // create the geospatial index
}
});
clubList.find({
$and:[{
loc: { $near: coords, $maxDistance: maxDistance }
},
{_id :{ $in: branchId}} //branchId : [108,109,110]
]},function(err, branchData){
if (err)
{
console.log(err);
}
else
{
console.log(branchData);
// Expecting sort near by branch of array [108,109,110]
}
數據應按近至遠順序排序。
看來您實際上是在要求$or
條件而不是$and
。 考慮到您是否真正想要“兩者”的結果,這將是有意義的:
作為$and
條件,查詢可以寫為:
clublist.find({
"loc": { "$near": coords, "$maxDistance": maxDistance },
"_id": { "$in": branchId } // branchId is the array [108,109,110]
},function(err,branchData) {
/* Data needs to be "both" near as well has having the supplied
_id values. So at maximum only "three" results, provided all
"three" are within the maxDistance
*/
})
因此,考慮到這一點,您似乎最有可能是$or
,但是還有另一個問題。
您不能將$or
與需要地理空間索引的查詢操作(如$near
一起使用。 因此,這樣的操作將出錯:
clublist.find({
"$or": [
{ "loc": { "$near": coords, "$maxDistance": maxDistance } },
{ "_id": { "$in": branchId } } // branchId is the array [108,109,110]
]
},function(err,branchData) {
// err: "geoNear must be top-level expr"
})
為此,您實際上希望運行單獨的查詢,然后合並結果。 由於這些實際上是單獨的結果,因此您可能還希望包含“距離”以對組合進行“排序”。
一個很好的工具是async.parallel
,因為它允許您從不同的操作中獲取結果並在一個回調中工作。 還有聚合$geoNear
,實際上將“距離”“ $geoNear
”到結果中,這是對整體結果進行排序的重要部分:
async.parallel(
[
function(callback) {
clublist.aggregate(
[
{ "$geoNear": {
"near": coords,
"distanceField": "distance",
"maxDistance": maxDistance
}},
{ "$limit": 50 }
],
callback
)
},
function(callback) {
clublist.aggregate(
[
{ "$geoNear": {
"near": coords,
"distanceField": "distance",
"query": { "_id": { "$in": branchId } }
}}
],
callback
)
}
],
function(err,results) {
if (err) throw err;
var branchData = [];
branchData = results.forEach(function(el) {
branchData = branchData.concat(el);
});
// Sort and return the 50 nearest
branchData = branchData.sort(function(a,b) {
return a.distance > b.distance
}).slice(0,50)
}
)
在這種情況下,您將分別運行每個查詢,其中一個"maxDistance"
是"maxDistance"
,而另一個"maxDistance"
是$in
的參數。 由於“組合”結果將大於設置的“極限”,因此您需要按距離對結果進行排序,然后從組合中返回總極限。
這就是您要考慮_id
選擇時要執行的操作,但是結果實際上可能返回“距離”,否則將不包括在$near
。
但是,如果您的意圖始終是在結果的“頂部”選擇_id
,則可以使用常規查詢並對這些結果“注入” 0
距離:
async.parallel(
[
function(callback) {
clublist.aggregate(
[
{ "$geoNear": {
"near": coords,
"distanceField": "distance",
"maxDistance": maxDistance
}},
{ "$limit": 50 }
],
callback
)
},
function(callback) {
clublist.find({ "_id": { "$in": branchId }}).toArray(function(err,branchData) {
branchData = branchData.map(function(doc) {
doc.distance = 0;
});
callback(err,branchData);
})
}
],
function(err,results) {
if (err) throw err;
var branchData = [];
branchData = results.forEach(function(el) {
branchData = branchData.concat(el);
});
// Sort and return the 50 nearest
branchData = branchData.sort(function(a,b) {
return a.distance > b.distance
}).slice(0,50)
}
)
然后,相同的排序將這些值放在最前面,並從其他查詢操作返回任何結果。
當然有“機會”在“兩個”查詢中都返回指定的_id
值。 但是,如果是這種情況,甚至是很可能,那么您可以在實際執行.slice()
操作之前或通常在返回最終結果之前,將數組內容與任何“重復的” _id
值進行.slice()
。 這是一個簡單的過程,使用具有唯一鍵的對象然后返回數組。
就像是:
function(err,results) {
if (err) throw err;
var branchData = [];
branchData = results.forEach(function(el) {
branchData = branchData.concat(el);
});
var uniqueBranch = {};
// Just keep unique _id for smallest distance value
for ( var idx in branchData ) {
if ( ( uniqueBranch.hasOwnProperty(branchData[idx]._id) )
&& ( branchData[idxx].distance > uniqueBranch[branchData[idx]._id].distance ) )
continue;
uniqueBranch[branchData[idx]._id] = branchData[idx];
}
// Go back to array, sort and slice
branchData = Object.keys(uniqueBranch).map(function(k) {
return uniqueBranch[k];
}).sort(function(a,b) {
return a.distance > b.distance;
}).slice(0,50);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.