Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB query produces OR response instead of AND

Tags:

mongodb

I'm using MongoDB version 2.6.5 and I have a collection that looks something like this:

{
  "_id": ObjectId("555a3398f4c572a44f877dcd"),
  "created": ISODate("2015-05-18T17:02:14.951Z"),
  "values": [
    {
      "value": "4",
      "label": "Apple"
    },
    {
      "value": "5",
      "label": "Peach"
    },
    {
      "value": "5",
      "label": "Banana"
    },
    {
      "value": "4",
      "label": "Orange"
    }
  ],
  "__v": 0
}
{
  "_id": ObjectId("555a74dbdfe135105faccdf7"),
  "created": ISODate("2015-05-18T21:27:37.064Z"),
  "values": [
    {
      "value": "2",
      "label": "Apple"
    },
    {
      "value": "3",
      "label": "Peach"
    },
    {
      "value": "4",
      "label": "Banana"
    },
    {
      "value": "5",
      "label": "Orange"
    }
  ],
  "__v": 0
}
{
  "_id": ObjectId("555a74f9dfe135105faccdfa"),
  "created": ISODate("2015-05-18T21:27:37.064Z"),
  "values": [
    {
      "value": "1",
      "label": "Apple"
    },
    {
      "value": "1",
      "label": "Peach"
    },
    {
      "value": "1",
      "label": "Banana"
    },
    {
      "value": "1",
      "label": "Orange"
    }
  ],
  "__v": 0
}

When I try to get the document that has a values.label of "Orange" AND values.value of "5" I should get one document back but I'm getting two:

> db.answers.count({ 'values.label':'Orange', 'values.value':'5' })
> 2

This is selecting the two documents with ids: 555a3398f4c572a44f877dcd (presumably because Banana also has a value of 5 ) and 555a74dbdfe135105faccdf7 (which is the only correct one). Can anyone think of why this is happening?

like image 758
jwerre Avatar asked Jun 03 '15 19:06

jwerre


1 Answers

You're using the dot notation (used to reach into objects) on an array. While that works in the way you described, it does imply OR-logic because the entire array is interpreted as an object, so to speak.

You're looking to match multiple criteria on documents in an array, which is what the $elemMatch operator is for, i.e.

db.answers.count({ 'values' : { '$elemMatch' : { 'label':'Orange', 'value':'5' } } })
like image 131
mnemosyn Avatar answered Sep 22 '22 14:09

mnemosyn