Mongo查询用于比较两个索引字段

时间:2016-01-04 10:57:21

标签: mongodb indexing mongodb-query

这个mongo查询还有其他选择

db.test.findAndModify(
{
   query:{$where:"this.field1<this.field2"},
   update:{$inc:{field2:1}},
   sort:{field2:1}
});

因为此查询扫描所有记录而不利用索引。

3 个答案:

答案 0 :(得分:1)

我建议您在文档中创建一个附加字段,该字段是field2field1之间的差异,然后在其上创建索引。

findAndModify()增加field2的查询中(从而增加差异),您应该增加difference字段:

db.test.findAndModify(
{
    query: {difference: {$gt: 0}},
    update: {$inc: {field2: 1, difference: 1}}
});

答案 1 :(得分:0)

根据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   
    }
}]);

答案 2 :(得分:0)

由于 $where 将在JavaScript中加载和评估并且不会使用任何索引,因此您最好的选择是创建一个额外的布尔字段,比如"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});