1

I have such structure of documents in my products collection:

{
  title: 'Samsung Galaxy S III',
  category_id: ObjectId("50bcc2f0b910a6c1936a4424"),
  properties: [
    {
      title: 'OS',
      value: 'Android'
    },
    {
      title: 'Display',
      value: '4.8"'
    }
  ]
}

Also I've created multikey index: {category_id: 1, 'properties.value': 1, 'properties.title': 1}

What happens when I do query with $all? How it works? Example:

{
  category_id: ObjectId("50bcc2f0b910a6c1936a4424"),
  properties: {
    $all: [
      {
        $elemMatch: {
          title: 'OS',
          value: 'Android'
        }
      },
      {
        $elemMatch: {
          title: 'Display',
          value: '4.8"'
        }
      }
    ]
  }
}

Does it find elements in index by first $elemMatch and then iterate over all found element to ensure second $elemMatch?

For my test collection with 2 androids and 1 ios explain() returns:

{
        "cursor" : "BtreeCursor category_id_1_properties.title_1_properties.value_1",
        "isMultiKey" : true,
        "n" : 1,
        "nscannedObjects" : 2,
        "nscanned" : 2,
        "nscannedObjectsAllPlans" : 2,
        "nscannedAllPlans" : 2,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "indexBounds" : {
            "category_id" : [
                    [
                            ObjectId("50bcc2f0b910a6c1936a4424"),
                            ObjectId("50bcc2f0b910a6c1936a4424")
                    ]
            ],
            "properties.title" : [
                    [
                            "OS",
                            "OS"
                    ]
            ],
            "properties.value" : [
                    [
                            "Android",
                            "Android"
                    ]
            ]
        }
}
1

First, not sure if you have altered the question or not since posted, but contrary to one of the answers, this is not doing a full collection scan, it is using an index, as evidenced by the "cursor" : "BtreeCursor in the explain output.

As for your question - you are asking about the $all operator, but I think your issue here is that you are using the $elemMatch operator incorrectly. When you do:

$elemMatch: {
          title: 'OS',
          value: 'Android'
        }

Or similar, you are running $elemMatch against a document, not an array, which is how it is intended. Hence the explain shows the bounds on the index as specific values of just OS and Android on properties.title and properties.value respectively rather than what you probably wanted, which I think is to only return if all the various properties are present in the array.

Try without $elemMatch:

{
  category_id: ObjectId("50bcc2f0b910a6c1936a4424"),
  properties: {
    $all: [
      {
          title: 'OS',
          value: 'Android'
      },
      {
          title: 'Display',
          value: '4.8"'
      }
    ]
  }
}
0

Yes. But in your case dataset is too small for effective using of index. So MongoDB decided to use full collection scan.

  • It use index at least for one $elemMatch. See, I've added "indexBounds". Does it decided to scan all found elements for second $elemMatch? – Dmitry Dec 7 '12 at 9:07
  • There are a few subquestions in the original post. Could you indicate here which one do you answer? Thanks in advance. – dezso Dec 7 '12 at 10:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.