MongoDB: Select element from array based on another property in the document

给你一囗甜甜゛ 提交于 2019-12-14 02:25:33

问题


I have a MongoDB collection with documents of the following structure (non-interesting bits left out):

{
  displayFieldId: "abcd",
  fields: [
    {
      fieldId: "efgh",
      value: "cake"
    },
    {
      fieldId: "abcd",
      value: "cheese"
    },
    ....
  ],
  ....
}

I would like to run a query on this collection to fetch only the element in the fields array which fieldId matches the document's displayFieldId. The result of the query on the document above should thus be:

{
  fields: [
    {
      fieldId: "abcd",
      value: "cheese"
    }
  ],
  ....
}

I constructed the following query. It does what I want, with the exception that the displayFieldValue is hard coded

db.containers.find({}, {
  fields: {
    $elemMatch: {
      fieldId: "abcd"
    }
  }
});

Is there a way to make it look at the document's displayFieldId and use that value instead of the hard coded "abcd"?


The server is running MongoDB 3.2.6

If possible, I would like to do this without aggregation, but if that can't be done, then aggregation will have to do


回答1:


With aggregation framework:

db.containers.aggregate([
    {        
        "$redact": { 
            "$cond": [
                { 
                    "$anyElementTrue": [ 
                        {
                            "$map": {
                                "input": "$fields",
                                "as": "el",
                                "in": { 
                                    "$eq": ["$$el.fieldId", "$displayFieldId"]
                                }
                            }
                        }
                    ] 
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    },
    {
        "$project": {
            "displayFieldId": 1,
            "fields": {
                "$filter": {
                    "input": "$fields",
                    "as": "el",
                    "cond": {
                        "$eq": ["$$el.fieldId", "$displayFieldId"]
                    }
                }
            },
            "otherfields": 1,
            ....
        }
    }
])

MongoDB 3.4:

db.containers.aggregate([
    {        
        "$redact": { 
            "$cond": [
                { 
                    "$anyElementTrue": [ 
                        {
                            "$map": {
                                "input": "$fields",
                                "as": "el",
                                "in": { 
                                    "$eq": ["$$el.fieldId", "$displayFieldId"]
                                }
                            }
                        }
                    ] 
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    },
    {
        "$addFields": {
            "fields": {
                "$filter": {
                    "input": "$fields",
                    "as": "el",
                    "cond": {
                        "$eq": ["$$el.fieldId", "$displayFieldId"]
                    }
                }
            }
        }
    }
])

Without aggregation framework - using $where (the slow query):

db.containers.find({
    "$where": function() {
        var self = this;
        return this.fields.filter(function(f){
            return self.displayFieldId === f.fieldId;
        }).length > 0;
    }
}).map(function(doc){
    var obj = doc;
    obj.fields = obj.fields.filter(function(f){
        return obj.displayFieldId === f.fieldId;
    });
    return obj;
})



来源:https://stackoverflow.com/questions/41744511/mongodb-select-element-from-array-based-on-another-property-in-the-document

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