0

Mongo Version : 4.0 (Cloud Atlas) I am trying to query a collection that has the following schema :

I am trying to use a simple find() query to mongo it matches the document but returns the whole complete document along with the arrays and sub document when I want only specific fields from what is received.

{

    "_id" : ObjectId("5d7b50ff3de5ce4c0371dc53"),
     "name" : "jane",
"bucket" : [
    {
        "bucket_name" : "Jane's Bucket",
        "bucket_sections" : [
            {
                "message":'Message for Herself'
                "name_from" : "jane",
                "name_to" : "jane",
            },
            {
                "message":'Message for John'
                "name_from" : "jane",
                "name_to" : "john",
            }
        ]
    }
]
}
,
{
    "_id" : ObjectId("5d7b50ff3de5ce4c0371dc53"),
"name" : "john",
"bucket" : [
    {
        "bucket_name" : "John 's Bucket",
        "bucket_sections" : [
            {
                "message":'Message for Himself'
                "name_from" : "john",
                "name_to" : "john",
            },
            {
                "message":'Message for Jane'
                "name_from" : "jane",
                "name_to" : "john",
            }
        ]
    }
]
}

I tried using a simple find command and projection.I could not get my head around aggregation yet !.

However my last resort would be to use pymongo and some python logic to extract what is required format(see below please) , however I believe this is mongos work

I looked at these examples which have some similarity with my problem but since my limited knowledge of mongo I could not make it to work

How to select a single field for all documents in a MongoDB collection?

Retrieve only the queried element in an object array in MongoDB collection

Here's in plain algorithm (sort of) of what I am trying to do.

John Searches for all "messages" and "name_from" where "name_to" belongs to john

Expected Output

[
{name_from:"jane","name_to":"john","message":"Message for John"},
{name_from:"john","name_to":"john","message":"Message for Himself"},    
]

I understand that this is a very specific problem to a very particular use case and schema , however I welcome any/all modifications and generalization to the question to help others understand better on this kind of problem. I also saw a lot of aggregation examples on stack , but they are not beginner friendly (Like looked really daunting and Wizardly cool!) so any helpful resources would be great (Except for documentation for its of great help !)

1 Answers1

1

A simple find query is probably not going to cut it, so aggregation framework it is.

You need to use the $unwind operator to turn the array into a document. Try this:

import pymongo

db = pymongo.MongoClient()['mydatabase']
db.message.insert_one({
    "name": "jane",
    "bucket": [
        {
            "bucket_name": "Jane's Bucket",
            "bucket_sections": [
                {
                    "message": 'Message for Herself',
                    "name_from": "jane",
                    "name_to": "jane"
                },
                {
                    "message": 'Message for John',
                    "name_from": "jane",
                    "name_to": "john",
                }
            ]
        }
    ]
})

db.message.insert_one({
    "name": "john",
    "bucket": [
        {
            "bucket_name": "John 's Bucket",
            "bucket_sections": [
                {
                    "message": 'Message for Himself',
                    "name_from": "john",
                    "name_to": "john",
                },
                {
                    "message": 'Message for Jane',
                    "name_from": "jane",
                    "name_to": "john",
                }
            ]
        }
    ]
})

messages = db.message.aggregate(
    [
        {"$unwind": "$bucket"},
        {"$unwind": "$bucket.bucket_sections"},
        {"$match": {"bucket.bucket_sections.name_to": "john"}},
        {"$project": {"bucket.bucket_sections": 1, "_id": 0}}
    ]
)

for message in messages:
    print(message['bucket']['bucket_sections'])
Belly Buster
  • 5,204
  • 2
  • 4
  • 15