Индексирование в поле, которое находится в массиве поддокументов

Я пытаюсь найти лучший дизайн для системы обмена сообщениями, которую я переношу с SQL Server на MongoDB - в настоящее время (в SQL Server) есть таблицы деревьев, которые хранят сообщение: Сообщения, Входящие и Отправленные. Сообщение сохраняется в таблице "Сообщения", а "Входящие/Отправленные" имеют записи для всех получателей/отправителей для каждого сообщения.

Теперь, в MongoDB, я хотел объединить эти три в одну коллекцию с такими документами:

{
    _id: 
    subject:
    body:
    sender: {memid:, name:}
    recip: [{memid:, name:}, {memid:, name:}, {memid:, name:}, etc]

}

Теперь мне нужно получить все сообщения для данного получателя memid, и мне нужно сделать это быстро, поэтому необходим индекс (у меня будут сотни миллионов таких записей). Итак, мой вопрос: могу ли я индексировать поле документа в массиве?

Ответ 2

Вы можете индексировать суб-ключи в mongo, однако я обнаружил, что производительность индексов на под-ключах в mongoDB довольно плоха, поскольку схемы похожи на то, как вы ее структурировали в вашем примере.

С тем, как у вас есть что-то написанное, похоже, что у вас будет структура в рецепте, которая выглядит так...

array(
    'recip' =>  array(
        '0' => array('memid' => 'some_id', 'name' => 'some_name'),
        '1' => array('memid' => 'another_id', 'name' => 'another_name'),
        '2' => array('memid' => 'yet_another_id', 'name' => 'yet_another_name')
    )   
)

Фактически вы не сможете установить индекс только для части memip документа с этой структурой, вместо этого вам нужно будет установить весь массив получателей. Это также будет иметь нежелательный побочный эффект индексации имен, а также снова и снова вводить одно и то же ключевое имя, теряя ценную память и вызывая неудовлетворительные запросы.

Я попытался бы структурировать документы таким образом...

array(
    'recip' => array(
        'memid' => array(
            '0' => 'some_id',
            '1' => 'another_id',
            '2' => 'yet_another_id',
        ),
        'name'  => array(
            'some_id'       => 'some_name',
            'another_id'        => 'another_name',
            'yet_another_id'    => 'yet_another_name'
        )
    )
)

Это образец, который послужил мне хорошим монго. Если вы структурируете документ, как это, вы сможете создать индекс в подмассе recip.memid, не забирая имена. Это, безусловно, будет намного лучше.

Я бы предположил, что у вас будет какое-то поле timestamp, а также для сортировки desc. Еще один индексный лакомый кусочек, который я узнал, заключается в том, что некоторые из драйверов mongo намного лучше выполняют запросы против больших коллекций, если метка времени добавляется как первое поле индекса.

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

Удачи с переходом. Я думаю, вам понравится работать с монго, как только вы его повесите.