mongodb query where nested object has > 0 properti

2019-02-20 15:40发布

问题:

EDIT - See the end of the question for one way to do it:

I have a mongo object with properties like:

{ something: { name: "asdf", childThing: {} } }

and

{ something: { name: "jklh", childThing: {"type": "blah"} } }

How can I write a query that will find the object somethingElse based on the fact that count(somethingElse.childThing.keys) > 0

I tried this but it's only for arrays, I guess, because it returns all records:

{ 'childThing': { $exists: true, $not: {$size: 0} } }

EDIT: I figured out one way to do this:

{ 'something.childThing': { $not: {$eq: {} } } }

This just matches all documents that have a non-empty value for that child

回答1:

You can use the $objectToArray operator to transform the childThing object to an array:

Converts a document to an array. The return array contains a element for each field/value pair in the original document.

This way you can get its size (which is the number of fields) and match it to being not 0:

db.collection.aggregate([
  { $addFields: {
    "childKeyCount": { "$size": { "$objectToArray": "$something.childThing" } }
  }},
  { $match: { "childKeyCount": { "$ne": 0 } } }
  // { $project: { "childKeyCount": false } }
])

Given this input:

[
  { "something" : { "name" : "asdf", "childThing" : {  } } }
  { "something" : { "name" : "jklh", "childThing" : { "type" : "blah" } } }
]

it gives:

[
  {
    "something" : { "name" : "jklh", "childThing" : { "type" : "blah" } },
    "childKeyCount" : 1
  }
]


回答2:

Use the $expr operator in your find() query as it allows the use of aggregation expressions within the query language. You would need an expression that transforms the object with the unknown keys to an array using $objectToArray and calculate the size of the array with $size to check the numbers of keys in the object. Once you get the size then run a comparison check with $gt to be used as the condition for $expr:

db.getCollection('collectionName').find({ 
    "$expr": {
        "$gt": [ { "$size": { "$objectToArray": "$something.childThing" } }, 0]
    }
})