1

I am playing around with mongodb and having troubles with finding elements in an array

My collection looks like this

{
        "_id" : ObjectId("4c4b1476238d3b4dd5000002"),
        "username" : "pbakkum",
        "first_name" : "Peter",
        "last_name" : "Bakkum",
        "age" : 21,
        "addresses" : [
                {
                        "name" : "home",
                        "street" : "588 5th Street",
                        "city" : "Brooklyn",
                        "state" : "CA",
                        "zip" : 11215
                },
                {
                        "name" : "work",
                        "street" : "588 5th Street",
                        "city" : "Brooklyn",
                        "state" : "CA",
                        "zip" : 11215
                },
                {

                }
        ]
}
{
        "_id" : ObjectId("4c4b1476238d3b4dd5000001"),
        "username" : "kbanker",
        "email" : "[email protected]",
        "first_name" : "Kyle",
        "last_name" : "Banker",
        "hashed_password" : "bd1cfa194c3a603e7186780824b04419",
        "addresses" : [
                {
                        "name" : "home",
                        "street" : "588 5th Street",
                        "city" : "Brooklyn",
                        "state" : "NY",
                        "zip" : 11215
                },
                {
                        "name" : "work",
                        "street" : "1 E. 23rd Street",
                        "city" : "New York",
                        "state" : "NY",
                        "zip" : 10010
                }
        ],
        "payment_methods" : [
                {
                        "name" : "VISA",
                        "last_four" : 2127,
                        "crypted_number" : "43f6ba1dfda6b8106dc7",
                        "expiration_date" : ISODate("2016-05-01T07:00:00Z")
                }
        ],
        "age" : 151
}

When I fire a query which is something like this.

db.users.find({"addresses.name":"home","addresses.state":"NY"});

the output of this query is a single record with the username as kbanker

This implies that it is exactly matching both the parameters "name":"home and addresses.state:NY and returning only one record.

However as per my understanding, this should return both the records since it should check for any of the parameters "name":"home" and addressess.state:NY in the enitre array and if any of them matches it should display that record.

This behavior of selecting just a single record defeats the purpose of $elemMatch attribute ?

Am I correct or something has changed in the new version of mongodb. I am using 3.2.5

1 Answer 1

3

Let me try to explain using your data set

db.foo.insert({
        "username" : "pbakkum",
        "addresses" : [
                {
                        "name" : "home",
                        "state" : "CA"
                },
                {
                        "name" : "work",
                        "state" : "CA"
                }
        ]
});
db.foo.insert({
        "username" : "kbanker",
        "addresses" : [
                {
                        "name" : "home",
                        "state" : "NY"
                },
                {
                        "name" : "work",
                        "state" : "NY"
                }
        ]
});

When you execute the query db.foo.find({"addresses.name":"home","addresses.state":"NY"}); mongo search in the array for documents that have "home" and "NY" it does not matter if the values are in the same document or not.

> db.foo.find({"addresses.name":"home","addresses.state":"NY"}, { "_id":0, "user
name" :1, "addresses" :1 })
{ "username" : "kbanker", "addresses" : [ { "name" : "home", "state" : "NY" }, {
 "name" : "work", "state" : "NY" } ] }

As you can see it will be enough to have "home" and "NY" in one of the array documents, the difference with $elemMatch is that both of them ("home" and "NY") need to be in the same document.

Lets add another document in the array of the username pbakkum.

db.foo.insert({
        "username" : "pbakkum",
        "addresses" : [
                {
                        "name" : "home",
                        "state" : "CA"
                },
                {
                        "name" : "work",
                        "state" : "CA"
                },
                {
                        "name" : "work",
                        "state" : "NY"  // Adding NY to make the match of your query
                }
        ]
});

Running the same query, this time you will see both records as both of them in the array contain "home" and "NY" in one of the documents

> db.foo.find({"addresses.name":"home","addresses.state":"NY"}, { "_id":0, "user
name" :1, "addresses" :1 })
{ "username" : "pbakkum", "addresses" : [ { "name" : "home", "state" : "CA" }, {
 "name" : "work", "state" : "CA" }, { "name" : "work", "state" : "NY" } ] }
{ "username" : "kbanker", "addresses" : [ { "name" : "home", "state" : "NY" }, {
 "name" : "work", "state" : "NY" } ] }

$elemMatch get only the document that have the perfect match within the same document ("home" and "NY")

> db.foo.find( { addresses : {$elemMatch : {"name":"home","state":"NY"}}}, { "_i
d":0, "username" :1, "addresses" :1 })
{ "username" : "kbanker", "addresses" : [ { "name" : "home", "state" : "NY" }, {
 "name" : "work", "state" : "NY" } ] }

This implies that it is exactly matching both the parameters "name":"home and addresses.state:NY and returning only one record.

Yes query is matching both parameters but not interesting if they are in the same document, this is just a coincidence.

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.