Понимание индекса в массиве поддокументов

Я изучал индексирование массивов (multi-key) на MongoDB, и у меня есть следующие вопросы, на которые я не смог найти много документации:

Индексы в массиве поддокументов

Итак, если у меня есть поле массива, которое выглядит примерно так:

{field : [
  {a : "1"}, 
  {b : "2"}, 
  {c : "3"}
  ]
}

Я запрашиваю только на field.a и field.c отдельно (не оба вместе), я считаю, что у меня есть выбор между следующими альтернативами:

  • db.Collection.ensureIndex({field : 1});
  • db.Collection.ensureIndex({field.a : 1}); db.Collection.ensureIndex({field.c : 1});

То есть: индекс для всего массива; или два индекса по встроенным полям. Теперь мои вопросы:

  • Как вы визуализируете индекс во всем массиве в опции 1 (это даже полезно)? Какие запросы полезны для такого индекса?
  • Учитывая ситуацию с запросом, которую я описал, какой из этих двух вариантов лучше, и почему?

Ответ 1

Вы правы, что если вы запрашиваете только значение a в массиве полей, оба индекса в некотором смысле помогут сделать ваш запрос более эффективным.

Однако просмотрите следующие 3 запроса:

> db.zaid.save({field : [{a: 1}, {b: 2}, {c: 3}] });
> db.zaid.ensureIndex({field:1});
> db.zaid.ensureIndex({"field.a":1});

#Query 1
> db.zaid.find({"field.a":1})
{ "_id" : ObjectId("50b4be3403634cff61158dd0"), "field" : [ { "a" : 1 }, { "b" : 2 }, { "c" : 3 } ] }
> db.zaid.find({"field.a":1}).explain();
{
    "cursor" : "BtreeCursor field.a_1",
    "nscanned" : 1,
    "nscannedObjects" : 1,
    "n" : 1,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : true,
    "indexOnly" : false,
    "indexBounds" : {
        "field.a" : [
            [
                1,
                1
            ]
        ]
    }
}

#Query 2
> db.zaid.find({"field.b":1}).explain();
{
    "cursor" : "BasicCursor",
    "nscanned" : 1,
    "nscannedObjects" : 1,
    "n" : 0,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : false,
    "indexOnly" : false,
    "indexBounds" : {

    }
}

#Query 3
> db.zaid.find({"field":{b:1}}).explain();
{
    "cursor" : "BtreeCursor field_1",
    "nscanned" : 0,
    "nscannedObjects" : 0,
    "n" : 0,
    "millis" : 0,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : true,
    "indexOnly" : false,
    "indexBounds" : {
        "field" : [
            [
                {
                    "b" : 1
                },
                {
                    "b" : 1
                }
            ]
        ]
    }
}

Обратите внимание, что второй запрос не имеет индекса на нем, даже если вы проиндексировали массив, но третий запрос. Выбор ваших индексов, основанных на том, как вы собираетесь запрашивать ваши данные, также важен, учитывая вопрос о том, нужен ли сам индекс. В Mongo структура вашего индекса может и очень сильно влияет на производительность ваших запросов, если вы не будете осторожны. Я думаю, это объясняет ваш первый вопрос.

Второй вопрос немного более открытый, но я думаю, что ответ снова заключается в том, как вы ожидаете запроса своих данных. Если вы будете только заинтересованы в сопоставлении значений "fields.a", вы должны сохранить комнату в памяти для других индексов, которые вам могут понадобиться в будущем. Если, однако, вы в равной степени можете запросить какой-либо из этих элементов в массиве, и вы вполне уверены, что массив не будет расти бесконечно (никогда не индексируйте массив, который со временем будет расти с неограниченным размером. не сможет индексировать документы, как только массив достигнет 1024 байтов в BSON.), тогда вы должны индексировать полный массив. Примером этого может быть документ для руки игральных карт, который содержит массив, описывающий каждую карту в руке пользователя. Вы можете индексировать этот массив, не опасаясь переполнения границы границы индекса, поскольку у руки не может быть более 52 карт.