Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to project only matching fields of nested array in mongo shell query

Tags:

arrays

mongodb

I am fairly new to mongodb, and I have what is hopefully a simple question:

I have a nested schema where I have a field that is an array, where each item of that array is an object that itself has an array field.

For example:

> db.mytest.insert({
    name: 'a',
    top: [
      {x:1, y:2, nest: [{p:1, q:2}, {p:2, q:3}]},
      {x:2, y:3, nest: [{p:4, q:5}, {p:6, q:7}]}
    ]
  })

I can query for certain values of p just fine, and can even limit my result to the first matching element of top:

> db.mytest.findOne({'top.nest': {$elemMatch: {p:6}}}, {'top.nest.$': 1})
{"_id":ObjectId(...), top: [{x:2, y: 3, nest: [{p:4, q:5}, {p:6, q:7}]}]}

Which brings me to my question: {'top.nest.$': 1} and {'top.$': 1} as my projection document both return the same result. How can I limit my search results to only include the first matching element of nest?

Do I need a second pass that iterates over the result of this style of query?

like image 378
ksprong Avatar asked Dec 13 '14 17:12

ksprong


1 Answers

Ok, the trick was the aggregation framework, specifically unwind.

> db.mytest.aggregate({$unwind: '$top'},
                      {$unwind: '$top.nest'},
                      {$match: {'top.nest.p': 6}}
  )

Though in the case that I had multiple sub matches in a single object, this would return multiple results instead of in their original grouped form. I suppose I can put a $group into the pipeline, though.

Though the related links I found suggested schema redesign as the only complete fix right now, so this is definitely better than nothing.

like image 177
ksprong Avatar answered Nov 24 '22 03:11

ksprong