1

I have a MongoDB collection whose structure is something like this:

/* 1 */
{
    "_id" : ObjectId("5c09a454dd42360001fd2515"),
    "conversations" : {
        "0" : {
            "message" : "Message 1",
              .
              .
              .
        },
        "1" : {
            "message" : "Message 1"
               .
               .
               .
        },
        "2" : {
            "message" : "Message 5"
              .
              .
              .
        },
        "3" : {
            "message" : "Message 1"
              .
              .
              .
        },
        "4" : {
            "message" : "Message 2"
              .
              .
              .
        },
        "5" : {
            "message" : "Message 3"

        },
        "6" : {
            "message" : "compliance"

        },
        "7" : {
            "message" : "Google"

        }
}

/* 2 */
{
    "_id" : ObjectId("5c09a673c2a98f00012f4efb"),

    "conversations" : {
        "0" : {
            "message" : "Message 11"

        },
        "1" : {
            "message" : "Google",

        },
        "2" : {
            "message" : "Message 7"

        }
}

/* 3 */
{
    "_id" : ObjectId("5c09f570173f7900015a82b2"),

    "conversations" : {
        "0" : {
            "message" : "Message 4"
        },

}

.
.
.

In above sample data, I have a set of documents inside the collection and within each document there is an array of dictionary field named conversations. Within this field I have list of dictionary fields(0,1,2...). What I want to do is filter all the documents where within each conversationsfield, the message value is Message 4.

I know the way to filter to a specific field within each document is db.getCollection('collection_1').find({conversation:""}), but I don't know how do I apply it to list of dictionary fields like for my case. Any help?

1 Answer 1

1

You need $objectToArray operator to turn an object with unknown keys into an array of k and v fields. Then inside of $expr you can apply $filter on that array to check if any message is equal to "Message 4"

db.collection.aggregate([
    {
        $match: {
            $expr: {
                $ne: [
                    {
                        $size: {
                            $filter: {
                                input: { $objectToArray: "$conversations" },
                                as: "conv",
                                cond: { $eq: [ "$$conv.v.message", "Message 4" ] }
                            }
                        }
                    },
                    0
                ]
            }
        }
    }
])

Example

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

4 Comments

Is the above answer very specific to the sample data I have? What if my documents have additional fields alongside conversations?
@user2966197 still you need to use $objectToArray if your keys are dynamically generated and it should still be working fine since conv.v will contain more than one field "message". You can try it out here: mongoplayground.net/p/tYJBT_ygKE5
Ok. And where in the query do I specify the collection name? My Collection name is "collection_1" and I don't see any place in above query to specify it? Will it be like db.conversation_1.aggregate()?
@user2966197 yes, just like you do it for .find()

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.