1

I have this type of data

{ 
"_id" : 6444, 
"name" : [
    {
        "name" : "John", 
        "sourcesID" : [
            1, 
            2
        ]
    }, 
    {
        "name" : "Jack", 
        "sourcesID" : [
            3, 
            4 
        ]
    }       
    ],
"address" : [
    {
        "city" : "Chicago", 
        "sourcesID" : [
            3, 
            4 
        ]
    }, 
    {
        "city" : "Boston", 
        "sourcesID" : [
            5, 
            6
        ]
    }       
]       

}

I want to aggregate the data so that I will be able to match a certain sourcesID and find all the information types that came from this source.

This is what I am looking to achieve

{"type" : "name", "sourceID" : 1}
{"type" : "name", "sourceID" : 2}
{"type" : "name", "sourceID" : 3}
{"type" : "name", "sourceID" : 4}
{"type" : "address", "sourceID" : 3}
{"type" : "address", "sourceID" : 4}
{"type" : "address", "sourceID" : 5}
{"type" : "address", "sourceID" : 6}

Thanks for your help.

2
  • Is it always sourcesID or sometimes sources and sometimes sourcesID or it's totally unpredictable ? Commented May 14, 2019 at 11:05
  • 1
    Good catch! It's a mistake in my example. All should be sourcesID. Will fix it now. Commented May 14, 2019 at 11:10

1 Answer 1

1

Assuming that there's always sourceID field you can run $objectToArray to transform be able to read object keys dynamically and then run $unwind three times to get single document per sourceID:

db.collection.aggregate([
    {
        $project: {
            data: {
                $filter: {
                    input: { $objectToArray: "$$ROOT" },
                    cond: {
                        $ne: [ "$$this.k", "_id" ]
                    }
                }
            }
        }
    },
    { $unwind: "$data" },
    { $unwind: "$data.v" },
    { $unwind: "$data.v.sourcesID" },
    {
        $project: {
            _id: 0,
            type: "$data.k",
            sourceID: "$data.v.sourcesID"
        }
    }
])

Mongo Playground

Sign up to request clarification or add additional context in comments.

Comments

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.