Mongo聚合$ match相当于{$ where:“this.field1!== this.field2”}

时间:2016-05-30 16:43:29

标签: javascript node.js mongodb mongoose

所以我有这个查询, db.collection.find({$where: "this.field1 !== this.field2"})

但是现在我需要创建一个类似的查询并将结果聚合在一个复杂的查询中,该查询尝试并且是真的,只能通过使用聚合管道或“使用cannon for a fly”并使用mapReduce选项来完成。

由于我想避免使用mapReduce,有没有办法实现类似于{$where: "this.field1 !== this.field2"}方法的东西?

一些观察,解决上述情况的一般方法的答案是最理想的,但如果不可能,为了解决我的问题,我也可以使用原始值在具有以下限制的查询中。我需要找到以下内容

db.collection.find({ $or :[
    {field1: value},
    {field2: value}
], $and: [
    { field1: {$not: {$eq: value}}},
    { field2: {$not: {$eq: value}} }
]})

我尝试了上述查询,但它丢弃了包含任一字段中值的结果,而我想要的是同时丢弃两个字段中具有相同值的对象的方法 ,但是获取在任一字段中具有值的文档,我通常更喜欢一种查询方法,但在阅读了很多之后,我认为避免mapReduce的唯一选择是做

之类的事情。
db.collection.find({$where: "this.field1 === this.field2"}, function (err, results){
    var match = { $or :[
        {field1: value},
        {field2: value}
        ], { 
        _id : { $not : {$in: results.map((x) => x._id)}}
    }
    db.collection([ {$match: match}, {$project: projectionObject}, ...., etc])
})

所以我将使用上面的解决方案,它可以进行很多优化,(我只是在编写问题时编写它),但我想避免将一个非常大的objectIds列表发送回数据库如果可能的话。我将在where语句

之前使用匹配运算符重构一下

1 个答案:

答案 0 :(得分:3)

这是一个复杂的案例,也许你可以在$cond内使用$project的技巧

var projectDataForMatch = {
    $project : {
        _id : 1, //list all fields needed here
        filterThisDoc : {
            $cond : {
                if  : {
                    $eq : ["$field1", "$filed2"]
                },
            then : 1,
            else  : 0
        } //or use compare operator $cmp
    }
}
}

var match = {
    $match : {
        filterThisDoc : 1
    }
}

db.col.aggregate([projectDataForMatch, match])    

您可以根据需要扩展$cond以满足您的需求。