MongoDB condition for all fields of array

半世苍凉 提交于 2019-12-11 20:47:53

问题


its possible in mongodb do a query for find documents where the field is an array and all its elements satisfy a condition?.

For example:

{
    "_id" : ObjectId("53d63d0f5c7ff000227cd372"),
     "works" : [ 
            {
                "code" : "A001",
                "items" : [ 
                    {
                        "_id" : "534664b081362062015d1b77",
                        "qty" : 6
                    }, 
                    {
                        "_id" : "534ba71f394835a7e51dd938",
                        "qty" : 5
                    }
                ],
                "name" : "Cambiar bombilla",
                "price" : 100,
                "Date" : "2014-07-30T09:43:17.593Z",
                "TechnicianId" : "538efd918163b19307c59e8e",
                "percent" : 2,
                "_id" : ObjectId("53d63d0f5c7ff002207cd372")
            }, 
            {
                "code" : "A001",
                "name" : "Cambiar bombilla",
                "price" : 100,
                "type" : "Bombillas",
                "TechnicianId" : "538efd918163b19307c59e8e",
                "date" : "2014-07-31T13:36:34.019Z",
                "orderId" : "53d63d0f5c7ff000007cd372",
                "_id" : ObjectId("53da466568c26f8a72b50fcb"),
                "percent" : 66
            }
        ]
},
{
    "_id" : ObjectId("53d63d0f5c7ff000007cd372"),
     "works" : [ 
            {
                "code" : "A001",
                "items" : [ 
                    {
                        "_id" : "534664b081362062015d1b77",
                        "qty" : 6
                    }, 
                    {
                        "_id" : "534ba71f394835a7e51dd938",
                        "qty" : 5
                    }
                ],
                "name" : "Cambiar bombilla",
                "price" : 100,
                "Date" : "2014-07-30T09:43:17.593Z",
                "TechnicianId" : "538efd918163b19307c59e8e",
                "percent" : 2,
                "_id" : ObjectId("53d63d0f5c7ff002207cd372")
            }, 
            {
                "code" : "A001",
                "name" : "Cambiar bombilla",
                "price" : 100,
                "type" : "Bombillas",
                "TechnicianId" : "538efd918163b19307c59e8e",
                "date" : "2014-07-31T13:36:34.019Z",
                "orderId" : "53d63d0f5c7ff000007cd372",
                "_id" : ObjectId("53da466568c26f8a72b50fcb"),
            }
        ]
}

I need to find the documents like first document because in works field his subdocuments have percent, but in the second document, works array at second position doesnt have percent.. I hope i explain me ok.


回答1:


It's not easy to test for the existence of a field in every element of an array in a simple way. Values can be tested for buy keys take a bit more work.

The approach is done with the aggregation framework in order to process conditions for the array elements and then match the result.

Firstly with MongoDB 2.6 and greater you get some helpers:

db.collection.aggregate([
    // Filter out to match only possible documents
    { "$match": {
        "works.percent": { "$exists": true }
    }},

    // Find matching through projection
    { "$project": {
        "works": 1,
        "matched": {
            "$allElementsTrue": {
                "$map": {
                    "input": "$works",
                    "as": "el",
                    "in": { "$ifNull": [ "$$el.percent", false ] }
                }
            }
        }
    }},

    // Filter to return only the true matches
    { "$match": { "matched": true } }

])

Or a bit longer and possibly slower with $unwind in prior versions:

db.collection.aggregate([
    // Filter out to match only possible documents
    { "$match": {
        "works.percent": { "$exists": true }
    }},

    // Unwind the array
    { "$unwind": "$works" },

    // Find matching by conditionally evaluating and grouping
    { "$group": {
        "_id": "$_id",
        "works": { "$push": "$works" },
        "matched": { 
            "$min": {
                "$cond": [
                    { "$ifNull": [ "$works.percent", false ] },
                    true,
                    false
                ]
            }
        }
    }}

    // Filter to return only the true matches
    { "$match": { "matched": true } }

])

In either case, it is the $ifNull operator that works as the equivalent of the $exists operator in a aggregation operator sense. Where the "query" form for $exists tests whether a field is present, $ifNull evaluates that where the field is present then the value is returned, otherwise the alternate argument is returned instead.

But the arrays basically need to be processed to see if all elements have the required field present as there is no standard query equivalent for this.



来源:https://stackoverflow.com/questions/25239624/mongodb-condition-for-all-fields-of-array

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