是否有此蒙戈查詢的任何替代蒙戈查詢比較兩個索引字段
db.test.findAndModify(
{
query:{$where:"this.field1<this.field2"},
update:{$inc:{field2:1}},
sort:{field2:1}
});
,因爲查詢掃描所有記錄,而不是採取索引的優勢。
是否有此蒙戈查詢的任何替代蒙戈查詢比較兩個索引字段
db.test.findAndModify(
{
query:{$where:"this.field1<this.field2"},
update:{$inc:{field2:1}},
sort:{field2:1}
});
,因爲查詢掃描所有記錄,而不是採取索引的優勢。
我建議你應該在你的文檔中創建一個額外的字段是field2
之間的差異, field1
,然後創建一個索引。
在你findAndModify()
查詢遞增field2
(從而增加差異),你應該增加與difference
場太:
db.test.findAndModify(
{
query: {difference: {$gt: 0}},
update: {$inc: {field2: 1, difference: 1}}
});
根據documentation,$where
運算符要求數據庫處理集合中每個文檔的JavaScript表達式或函數。這意味着表達式"this.field1<this.field2"
被視爲JavaScript表達式,因此不使用這些索引。
但是,您不能在本地(無JavaScript)使用find
查詢比較MongoDB中的兩個字段,但可以使用聚合框架來達到此目的。通過使用$match
操作,你可以做類似下面的代碼片段的東西:
db.data.aggregate([{
$project : {
equal : {
$eq : ["$field1", "$field2"]
},
doc : "$$ROOT" // store the whole document, this is optional
}
}, {
$match : {
equal : true
}
}]);
由於$where
將在JavaScript加載和eval,不會使用任何指標,你最好的選擇是創建一個額外的布爾字段,例如"isField2GreaterThanField1"
,在包含布爾結果(field1 < field2)
的文檔模式中。
要創建額外的領域,你將不得不遍歷從find()
操作的結果,並更新循環中的集合:
db.test.find({}).forEach(function(doc) {
var comparison = (doc.field1 < doc.field2);
db.test.update(
{ "_id": doc._id },
{
"$set": {
"isField2GreaterThanField1": comparison
}
}
);
});
性能比較與上面的更新操作可如果處理受到影響大型集合,但使用Bulk API可以通過減少發送到服務器的更新操作的數量來簡化更新以獲得最大效率,每1000個排隊操作發送一次:
var bulk = db.test.initializeOrderedBulkOp(),
counter = 0;
db.test.find({}).forEach(function(doc) {
var comparison = (doc.field1 < doc.field2);
bulk.find({ "_id": doc._id }).updateOne({
"$set": {
"isField2GreaterThanField1": comparison
}
});
counter++;
if (counter % 1000 == 0) {
// Execute per 1000 operations and re-initialize every 1000 update statements
bulk.execute();
bulk = db.test.initializeOrderedBulkOp();
}
});
// Clean up queues
if (counter % 1000 != 0){
bulk.execute();
}
在創建了新的領域,你就可以在其上創建一個索引和查詢文檔中
db.test.find({"isField2GreaterThanField1": true});
實際上,你有什麼指標,並在這些領域是什麼類型的數據? – Alnitak
{field1:1},{field2:1} – kamesh
並且這些字段是數字或字符串? – Alnitak