Индекс неизвестных данных

22 views
Skip to first unread message

Дмитрий Михайлов

unread,
Dec 25, 2014, 4:55:20 AM12/25/14
to mongodb-us...@googlegroups.com
Всем привет.

Пытаюсь решить как лучше сделать. И с индексированием похоже проблемы. У меня имеется набор критериев для документов, которые часто будут использоваться в запросах. Документ выглядит примерно так:

Главный документ {
    ид
    много разных полей

    Тэги [
                "поле1" : 10
                "поле2" : 1
                "поле3" : 14
                "поле4" : 2
                "поле5" : 0
               и т.д. 
             ]
}

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

Тэги [
               {п: "поле1" , з:10}
               {п: "поле2" , з:1}
                {п: "поле3" , з:14}
               и т.д. 
             ]

Но это не рекомендуется и должно применяться только после проверки на реальных данных, т.к. сильно раздувает индекс. А если индекс будет большим, то может не поместиться в память и работать всё будет медленно. Я так понимаю индекс будет размером как сами данные.

Может лучше тогда сделать Тэги в отдельные документы? Типа как в РБД. Т.е. каждое поле содержится в своем документе, в котором есть ссылка на Главный документ с остальными данными. Тогда индекс будет обычным, а запросы делать сначала к документам Гэгов и получив из них ИДы Главных документов строить следующей запрос уже по Главным документам. Т.е. по два запроса по двум коллекциям вместо одного запроса в одну коллекцию.

Оба варианта какие-то не такие, что выбрать не знаю. Может есть ещё какие-то способы?

Serge Matveenko

unread,
Dec 25, 2014, 5:02:03 AM12/25/14
to mongodb-us...@googlegroups.com
Бывает, что можно внести в запрос некоторые дополнительные фильтры по
известным полям, по которым строить индекс, и тогда по тэгам можно
делать full scan без индекса.
> --
> You received this message because you are subscribed to the Google Groups
> "MongoDB по-русски" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to mongodb-user-rus...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



--
Serge Matveenko
mailto: se...@matveenko.ru
github: http://lnkfy.com/1
linkedin: http://lnkfy.com/S

Дмитрий Михайлов

unread,
Dec 25, 2014, 5:17:28 AM12/25/14
to mongodb-us...@googlegroups.com, s...@matveenko.ru
К сожалению в моем случае именно Тэги должны позволять отбирать несколько Главных документов, а в Главных ничего особенного для запроса нет. Т.е. у меня может быть скажем 100 Главных документов в которых есть Тэги с полем1 и полем2, у которых значение больше или меньше какого-то числа. Но они есть только в 5 из 100 Главных документов, поэтому мне тогда придется просмотреть все Главные документы, чтобы найти только 5 нужных. В моем случае индексирование по этим Тэгам обязательно, как я это понимаю.

четверг, 25 декабря 2014 г., 17:02:03 UTC+7 пользователь lig написал:

Serge Matveenko

unread,
Dec 25, 2014, 5:53:14 AM12/25/14
to Дмитрий Михайлов, mongodb-us...@googlegroups.com
Ну, тогда можно попробовать пойти путем создания структуры {tags:
[{name: ..., value: ...}, {name: ..., value: ...}, {name: ..., value:
...}]}, но делать индекс не по `tags`, а по `tags.name` или по
`[tags.name, tags.value]`, если объем данных позволит. В случае с
tags.name индекс будет меньше, чем в другом варианте, но будет
выбираться больше документов, которые уже будут обрабатываться по
запросу к `tags.value`.

Дмитрий Михайлов

unread,
Dec 25, 2014, 6:21:08 AM12/25/14
to mongodb-us...@googlegroups.com, dmiha...@gmail.com, s...@matveenko.ru
Это почти что как раз тот вариант, о котором я написал в самом начале, тот что создает огромные индексы. Т.е. вот это " {п: "поле1" , з:10}, {п: "поле2" , з:1}" Просто не смог более понятно, чем вы, описать.
Использовать в индексе только название Тэга, конечно вариант, но наверное индекс будет не намного меньше, потому что у меня значения просто цифры. Скорость запроса уменьшится если брать только названия, но размер индекса тоже станет меньше. Пока это получается лучший вариант.

Может мне как-то структуру самого документа изменить, а я не  знаю как по неопытности? Например индексы из массивов ([полу1, поле2, поле3]) приподняться как преимущество Монго и значит работает быстро и индекс не сильно увеличивает по сравнению с вариантом индекса структуры (не знал как это назвать:-)) 

У меня кстати есть в Главном документе такие массивы, которые тоже будут постоянно использоваться совместно со структурами и даже в одном запросе. Вот если бы можно было названия полей Гэгов хранить в массиве и строить по нему индекс, а значения где-то ещё в документе, и как-нибудь их сопоставлять. Но похоже так не реально сделать. Но я бы тогда Тэги из массива и из структуры мог бы в одном поле держать и значит было бы на 1 индекс меньше.

четверг, 25 декабря 2014 г., 17:53:14 UTC+7 пользователь lig написал:

Serge Matveenko

unread,
Dec 25, 2014, 6:42:54 AM12/25/14
to Дмитрий Михайлов, mongodb-us...@googlegroups.com
В реальности разницы между индексом по значениям массива и значениям
ключа словаря в массиве, на сколько я понимаю, нет. На каждое значение
создается отдельная запись в индексе.

Можно еще попробовать действительно выделить тэги в отдельные
доументы, например, так: `{_id: <tag_name>, docs: {doc_id:
<ref_doc_id>, value: <tag_value_for_doc>}}`. В зависимости от
запросов, может не понадобится никакие индексы дополнительные делать.
Может быть полезным добавить сюда какие-то поля из документов, чтобы
не лезть в коллекцию к ним для вывода спсика результатов запросов, но
придется лениво обновлять после каждого иззменения этих данных в
документе. Также может быть полезным внести список тегов в документ,
но тоже придется лениво обновлять коллекцию со значениями по тегам.

Дмитрий Михайлов

unread,
Dec 25, 2014, 7:13:29 AM12/25/14
to mongodb-us...@googlegroups.com, dmiha...@gmail.com, s...@matveenko.ru
Спасибо, интересный вариант. Я как-то более прямолинейно это видел, типа для каждой пары Тэг:Значение делать свой документ, а тут как бы получиться один Тэг со списком Главных документов и значений. Только жаль, что придется записывать и делать запросы в двух коллекциях, хотя часть значений из Главного документа действительно можно будет перенести в документ Тэга. Получается типа один ко многим, один Тэг во многие Главные документы. С обновлением двух коллекций как раз пригодились бы транзакции из РБД.

четверг, 25 декабря 2014 г., 18:42:54 UTC+7 пользователь lig написал:

Serge Matveenko

unread,
Dec 25, 2014, 7:30:36 AM12/25/14
to mongodb-us...@googlegroups.com
Обычно в таких ситуациях делают параллельный процесс, который
обновляет зависимую коллекцию. Например, можно воспользоваться
каким-нибудь брокером сообщений, чтобы активировать задачи по
обновлению данными из определенного документа.

Теоретически никто не мешает хранить значения в основном документе,
причем удобным образом в виде {tags: {tag_1: tag_1_value, tag_2:
tag_2_value, ..., tag_N: tag_N_value}}, а из этой коллекции уже делать
коллекцию с данными, например, с помощью Map/Reduce. И потом
отслеживать изменения значений тегов и обновлять поисковую коллекцию.
> --
> You received this message because you are subscribed to the Google Groups
> "MongoDB по-русски" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to mongodb-user-rus...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



Arthur Metasov

unread,
Dec 25, 2014, 11:54:34 AM12/25/14
to mongodb-us...@googlegroups.com
А какая разница? 
Размер коллекции меньше размера индекса не будет.
Всё равно для быстрого поиска нужно будет чтоб минимально необходимые данные в память помещались.

25 дек. 2014, в 13:21, Дмитрий Михайлов <dmiha...@gmail.com> написал(а):

Reply all
Reply to author
Forward
0 new messages