Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.3k views
in Technique[技术] by (71.8m points)

mongodb - Aggregate documents where objects in array matches multiple conditions

I have a collection with documents similar to such:

{
    "_id": ObjectId("xxxxx"),
    "item": [
        { "property": ["attr1", "+1"] },
        { "property": ["attr2", "-1"] }
    ]
}

{
    "_id": ObjectId("xxxxy"),
    "item": [
        { "property": ["attr1", "-1"] },
        { "property": ["attr2", "0"] }
    ]
}

{
    "_id": ObjectId("xxxxz"),
    "item": [
        { "property": ["attr1", "0"] },
        { "property": ["attr2", "+1"] }
    ]
}

Preferably using an aggregation pipeline, is there any way to match the document if and only if any one of the properties match more than one condition?

For example, I want a query where one object in the array matches both of these conditions:

("item.property": "attr1") AND ("item.property": /^+/)

That is, a single property where it contains "attr1" and an element that starts with "+".

However, using my current query that looks like this:

collection.aggregate(
    { $match:
        { $and: 
            [
                { "item.property": "attr1" },
                { "item.property": /^+/ }
            ]
        }
    }

This would match both the first and last document because both contain a property with "attr1" and an element that stats with "+". However, I do not want this query to match the last document, since the element that starts with "+" does not belong to the same object in the array.

Is there any way to achieve this behavior using the aggregation framework?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use the below query with $elemMatch to match the array's both values.

Something like

db.collection_name.aggregate({
  "$match": {
    "item": {
      "$elemMatch": {
        "property.0": "attr1",
        "property.1": /^+/
      }
    }
  }
});

Also, you can use $all operator if you don't want to reference array index.

db.collection_name.aggregate({
  "$match": {
    "item": {
      "$elemMatch": {
        "property": {
          "$all": [
            "attr1",
            /^+/
          ]
        }
      }
    }
  }
});

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...