запрос быстрых тегов mongodb

У меня очень большая коллекция (более 800 тыс.), и мне нужно реализовать запрос для функции автозаполнения (только на основе начала слов) на основе тегов. мои документы выглядят так:

 {
    "_id": "theid",
    "somefield": "some value",
    "tags": [
        {
            "name": "abc tag1",
            "vote": 5
        },
        {
            "name": "hij tag2",
            "vote": 22
        },
        {
            "name": "abc tag3",
            "vote": 5
        },
        {
            "name": "hij tag4",
            "vote": 77
        }
    ]
}

если, например, мой запрос будет для всех тегов, которые начинаются с «ab» и имеют «somefield», который является «некоторым значением», результатом будет «abc tag1», «abc tag3» (только имена). Меня гораздо больше волнует скорость запросов, чем скорость вставок и обновлений.

Я предполагаю, что фреймворк агрегации был бы правильным решением, но что было бы лучшим конвейером и индексами для очень быстрых запросов?

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


person jacob    schedule 29.09.2014    source источник
comment
Я пытался сделать что-то подобное в прошлом году, но с гораздо меньшей базой данных. В итоге мне пришлось использовать Solr по мере роста объема данных.   -  person Martin    schedule 29.09.2014
comment
Можете ли вы опубликовать запрос и индексы, которые вы пробовали? Вы использовали структуру агрегации?   -  person jacob    schedule 29.09.2014
comment
Извините, кода давно нет, но он был основан на регулярных выражениях в поле тега. Он предшествовал структуре агрегации, но я не уверен, что в любом случае это будет лучший подход. По моему опыту, фреймворк агрегации любит считывать в память целые документы, даже если $match может быть выполнен с использованием только индекса.   -  person Martin    schedule 30.09.2014


Ответы (1)


Структура вашего документа не имеет смысла - я предполагаю, что tags - это массив, а не объект. Попробуйте такие запросы

db.tags.find({ "somefield" : "some value", "tags.name" : /^abc/ })

с индексом на { "maintag" : 1, "tags.name" : 1 }. MongoDB оптимизирует запросы регулярных выражений с левой привязкой в ​​запросы диапазона, которые могут быть эффективно выполнены с использованием индекса (см. используйте" rel="nofollow">$regex docs).

Вы можете получить только теги из этой структуры документа, используя конвейер агрегации:

db.tags.aggregate([
    { "$match" : { "somefield" : "some value", "tags.name" : /^abc/ } },
    { "$unwind" : "$tags" },
    { "$match" : { "tags.name" : /^abc/ } },
    { "$project" : { "_id" : 0, "tag_name" : "$tags.name" } }
])

Индекс помогает только для первого совпадения $, поэтому для конвейера используются те же индексы, что и для запроса.

person wdberkeley    schedule 30.09.2014
comment
вы были правы, у меня была ошибка в моем объекте, я ее исправил. ваш запрос вернет все документы, соответствующие условию, мне нужен только список тегов, которые подходят без дубликатов. в противном случае я получу много ненужных данных. - person jacob; 30.09.2014
comment
Позиционный оператор $ может спроецировать 1 соответствующий тег. Если вам действительно нужно вернуть все теги, значит, вы неправильно структурировали свои документы. Документы должны быть тегами с денормализованным в них основным тегом, а не документом основного тега с прикрепленными к нему тегами. - person wdberkeley; 30.09.2014
comment
Думаю, я не совсем ясно выразился в своем вопросе, пожалуйста, посмотрите мое редактирование. это не документ тега, это клиентский документ с вложенным деморализованным массивом тегов. - person jacob; 30.09.2014
comment
То же самое — запросы возвращают документы, а не встроенные объекты. Вы должны вставить то, что вы хотите, чтобы ваши запросы возвращали в базу данных. Для более редких вещей используйте агрегацию. Это может быть более редкий запрос, поэтому я обновил ответ, указав, как получить теги с помощью агрегации. - person wdberkeley; 30.09.2014
comment
спасибо, это работает, но будет ли это масштабироваться для более чем 800 тыс. документов? Мне нужно это для автозаполнения ввода, по вашему мнению, будет ли это достаточно быстро? должен ли индекс быть на тегах или tags.name ? - person jacob; 01.10.2014
comment
Это должно быть на tags.name - забыл исправить, когда я написал tags вместо tags.name, когда я впервые написал ответ, прежде чем я его проверил. Я исправил это в исходном ответе. Единственный способ узнать это - попробовать, но 800 КБ - это не очень много документов, поэтому я думаю, что это будет работать на стандартном оборудовании, если вы делаете простые совпадения префиксов, чтобы можно было оптимизировать регулярные выражения. - person wdberkeley; 01.10.2014