Use $or with $elemMatch and condition outside of Array

。_饼干妹妹 提交于 2020-01-13 19:37:43

问题


My basic structure is I have User object with a session object that contains a subjectId and an hourly price.

User{
    defaultHourly: Number,
    subjects{
        [
            id: String,
            hourly: Number
        ]
    }
}    

I use elemMatch like this:

query.elemMatch("subjects", {
                "id": { $in: subjects },
                "$or": [
                    { "hourly": { $eq: null } }, // this is my issue
                    {
                        "$and": [
                            { "hourly": { $ne: null } },
                            { "hourly": { $gte: price.low, $lte: price.high } }
                        ]
                    }
                ]
            });

the first part of elemMatch makes sure that the subjectId I want is in the array of subjects. Then I want to filter by price. if a User has null in the hourly field, I want to then compare the defaultHourly to price.low and price.high.

The issue is that defaultHourly is not a field in subjects, but is a field in the parent of subjects so I'm not sure how to access it.

I want to write:

"$or": [
           { 
                "$and": [
                   { "hourly": { $eq: null } },
                   { "defaultHourly": { $gte: price.low, $lte: price.high } } //this doesnt work because default hourly is not a field.
                ]
           },
           {
               "$and": [
                   { "hourly": { $ne: null } },
                   { "hourly": { $gte: price.low, $lte: price.high } }
                ]
            }
       ]
 }); 

How can I do this multilevel comparison?


回答1:


You write the condition outside of the $elemMatch, and put the $or at the top level of the document. This allows each "set" of conditions to apply:

User.find({
  "$or": [
     { 
       "defaultHourly": { "$gte": price.low, "$lte": price.high },
       "subjects": {
         "$elemMatch": { 
           "id": { "$in": subjects },
           "hourly": { "$eq": null }
         }
       }
     },
     {
       "subjects": {
         "$elemMatch": {
           "id": { "$in": subjects },
           "hourly": { "$gte": price.low, "$lte": price.high }
         }
       }
     }
  ] 
})

Also note the $ne is not needed, since the "range" comparison would actually negate null since it simply would not be "greater than" an actual numeric value.

In addition, note that ALL MongoDB query expressions are already AND conditions, such as the $gte and $lte on the same property. So even though it's not required, the $ne can also be written in as:

   "hourly": { "$gte": price.low, "$lte": price.high, "$ne": null }

Which removes any need for an explicit $and.



来源:https://stackoverflow.com/questions/44786973/use-or-with-elemmatch-and-condition-outside-of-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!