MongoDB: Как проиндексировать неизвестные поля - PullRequest
0 голосов
/ 26 сентября 2018

Мы храним документы с неопределенной структурой.Я имею в виду, что он имеет базовую структуру (id, user и creationTimestamp), но есть также поля Map<String, Object> values, в которых мы можем хранить любую структуру:

public class Metadata {
    private String id;
    private String user;
    private Date creationTimestamp;
    private Map<String, Object> values;
}

Пример:

> db.metadata.find();
{
    "_id" : "Doc2Ref2Mdt1",
    "user" : "user1",
    "creationTimestamp" : ISODate("2018-09-24T12:20:56.958Z"),
    "values" : {
        "ambit" : "ctti",
        "departament" : "economia"
    }
},
{
    "_id" : "Doc1Ref2Mdt1",
    "user" : "user2",
    "creationTimestamp" : ISODate("2018-09-24T12:20:56.169Z"),
    "values" : {
        "date" : ISODate("2018-09-24T12:20:56.171Z"),
        "number" : 16,
        "address" : {
        "street" : "Av. Diagonal",
        "location" : "barcelona",
        "credentials" : [
        {
            "password" : "pwd",
            "login" : "main"
        },
        {
            "password" : "pwd",
            "login" : "other",
            "creation" : ISODate("2018-09-24T12:20:56.171Z")
        }],
        "contact" : "contact name",
        "tags" : ["tag1", "tag2"}]
    }
}

Итак, вы можете видеть, что values может хранить любую структуру.

Мне нужно знать, может ли mongodb автоматически проиндексировать все из них.

Я имею в виду, когда новое поле «добавляется» в values, например, values.newfield, оно автоматически индексируется.

Есть идеи?

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

Невозможно так, как вы хотите.

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

Есть несколько ограничений, о которых следует помнить:

  • будут проиндексированы только строковые поля, например, .find({ $text: { $search: "2018-09-24" } }) ничего не вернет..find({ $text: { $search: "16" } })
  • также не будет запрашивать только полные слова, то есть не будет регулярных выражений.Вам нужно будет использовать language: "none", чтобы сохранить стоп-слова и не использовать стеминг.Такие запросы, как .find({ $text: { $search: "barcel" } }), не найдут второй документ.

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

0 голосов
/ 26 сентября 2018

вы можете создать индекс для вложенного документа, и новое поле будет добавлено автоматически,

НО

Чтобы использовать этот индекс с вашими запросами, вы должны предоставитьв качестве параметра заполните и упорядочите документ.

Пример с вашим образцом:

db.metadata.createIndex({"values",1});

db.metadata.find ("values.ambit ":" ctti ")

==> НЕ будет использовать индекс, но вернет первый документ.

db.metadata.find (values:{ambit: "ctti"})

==> Будет использовать индекс, но не вернет документ.

db.metadata.find (values: {"departament":" economia ", ambit:" ctti "})

==> Будет использовать индекс, но не вернет документ из-за порядка полей.

db.metadata.find (values: {ambit: "ctti", "departament": "economia"})

==> Будет использовать индекс и вернет возврат первого документа.

...