1

I have a document that contains an array. Like so:

"_id" : ObjectId("55101f81e4b07caf8554b9b1"),
"myId" : "1222222",
"isDelayed" : false,
"status" : "BALLS",
"yellow" : false,
"white" : true,
"people" : [ 
    {
        "peopleId" : 222222,
        "bc" : 0,
        "status" : "live",
        "fc" : 1,
        "tc": 4,
        "rc": "yellow" 

    }, 
    {
        "peopleId" : 33312,
        "bc" : 0,
        "status" : "live",
        "fc" : 1,
        "tc": 4,
        "rc": "yellow" 

    }, 
  ...

I have a mongo query like below, in the collection mycoll, if myId=1.222 and in the people array if people.peopleId=1123 it returns the first match:

db.getCollection('mycoll').find(
    {myId:'1.222',
        people: { $elemMatch: { peopleId: 1123 }
                 }
    },{"people.$": 1 }).pretty();

The result includes all fields in the people entry from the array:

"people" : [ 
        {
            "peopleId" : 1122,
            "bc" : 0,
            "status" : "live",
            "fc" : 1,
            "tc": 4,
            "rc": "yellow" 

        }, 

How do I filter the reply that it only returns the desired field from the matching entry in the inner array, say "status"? I can generate a filter for the outer document but not a field in an array element.

2 Answers 2

5

You can do this using aggregation. What you need to do is:

  1. Match the documents with the desired myId.
  2. Unwind the people arrays so that there is one document per subdocument inside people.
  3. Match the specified peopleId.
  4. Project fields as desired.
db.mycoll.aggregate([
    { "$match": { "myId": "1.222"} },
    { "$unwind": "$people" },
    { "$match": { "people.peopleId": 1123 }},
    { "$project": { "peopleId": "$people.peopleId",
                    "status": "$people.status" }
    }
]).pretty();
Sign up to request clarification or add additional context in comments.

Comments

1

Mongo $elemMatch in projection used in projection to find out specific field in your case status below query return only status field

db.collectionName.find({"myId":"1222222"},{"people":{"$elemMatch":{"peopleId":33312}},"people.status":1}).pretty()

3 Comments

Hi @yogesh, yes but this will return 'status' for all elements of the array instead of just the matching one
@user1843591 I think you should misplaced some thing, this shows me exact matching result status result as below {"_id" : ObjectId("55101f81e4b07caf8554b9b1"),"people" : [{"status" : "live"}]}
you're right, my apologies, it 'looked' like my attempt at it but i didn't actually try it out. thank you for your reply, I'm going to mark the answer by @juancarlos as correct as his solution will return the exact matches (all criteria) whereas this solution will return an 'empty' result for all entries that match "myId":"1222222" even if $elemMatch does not return anything.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.