Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongo aggregation $match equivalent of {$where: "this.field1 !== this.field2"} [duplicate]

So I have this query, db.collection.find({$where: "this.field1 !== this.field2"})

But now I need to create a similar query and aggregate the results in a complex query which tried and true, only can be done by using the aggregation pipeline or go "cannon for a fly" and use the mapReduce option.

Since I want to avoid mapReduce, is there a way to achieve something similar to the {$where: "this.field1 !== this.field2"} approach?

Some observations, an answer to the general approach to solve the situation above is most desirable, but in case that is not possible, in order to solve my problem, I can also use the raw value in the query with the following restrictions. I need to find what follows

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

I tried the above query but it discards results that contains the value in either field, and what I want is a way to discard the objects that have the same value in both fields at the same time, but obtain the documents that have the value in either field, I usually prefer an one query approach but after reading a lot, I think the only alternative to avoid mapReduce, is to do something like

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])
})

So I'm going to use the be solution above, which can be optimized a lot, (I just wrote it while writing the question), but I would like to avoid sending an incredibly big list of objectIds back to the database if at all possible. I will refactor it a bit to use matching operators before the where statement

like image 798
galileopy Avatar asked Jan 26 '26 08:01

galileopy


1 Answers

that's complex case, and maybe you could use a trick with $cond inside $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])    

you can extend $cond to fit your needs as desired.

like image 102
profesor79 Avatar answered Jan 28 '26 06:01

profesor79



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!