Частичный текстовый поиск в MongoDB - создайте поле только для данных поиска - PullRequest
1 голос
/ 10 марта 2020

Справочная информация:

Я работаю над сторонним проектом с открытым исходным кодом, который использует Mon go в качестве базы данных. Предполагается, что проект представляет собой 'каталог репозитория' .

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

Требования:

Основная цель наличия каталога состоит в том, чтобы его можно было легко и надежно искать, а также полагаться на «частичные совпадения».
Итак Например, если проект называется «XmlValidator», я смогу найти его по строке поиска «Xml».
Если проект содержит файл с именем «GoogleDriveSynchronizer.cs», я смогу найти его. это 'Google' или 'GoogleDrive' et c.
Это не работает "из коробки".

Поиск также должен быть быстрым.
Размер мудрый Реально я не ожидаю превышения 10000 документов, а средний размер документа составляет 2 КБ, но, скажем, я хочу, чтобы он работал хорошо даже при 100 КБ документов среднего размера 3 КБ. Из-за производительности я не рассматриваю поиск по регулярному выражению (хотя я не уверен , возможно, 100 КБ документов по 3 КБ не сложно просмотреть?)

Текущая ситуация:

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

IndexKeysDefinition<ProjectInfo> keys = Builders<ProjectInfo>.IndexKeys
                .Text(x => x.ProjectName)
                .Text(x => x.ProjectDescription)
                .Text(x => x.AssemblyName)
                .Text(x => x.ProjectUri)
                .Text(x=>x.Tags)
                .Text($"{nameof(ProjectInfo.Properties)}.{nameof(Property.Value)}")
                .Text($"{nameof(ProjectInfo.Components)}.{nameof(ComponentManifest.Name)}")
                .Text($"{nameof(ProjectInfo.Components)}.{nameof(ComponentManifest.Description)}")
                .Text($"{nameof(ProjectInfo.Components)}.{nameof(ComponentManifest.DocumentationUri)}")
                .Text($"{nameof(ProjectInfo.Components)}.{nameof(ComponentManifest.Tags)}")
                ;

Образец документа

       "_id": {
            "$oid": "5e67ce562ee2d4d141822a17"
        },
        "AddedDateTime": {
            "$date": {
                "$numberLong": "1583861334692"
            }
        },
        "ProjectName": "XmlValidatorFake",
        "Autogenerated": false,
        "Owner": null,
        "ProjectDescription": null,
        "ProjectUri": null,
        "DocumentationUri": null,
        "DownloadLocation": null,
        "AssemblyName": null,
        "OutputType": null,
        "TargetExtension": null,
        "RepositoryId": {
            "$oid": "5e67ce558d980a7b344dac5f"
        },
        "RepositoryStamp": "2020-03-10T17:28:54.8444190Z",
        "Tags": [],
        "Properties": [{
            "Key": "Files", 
//the value will more often be a normal string, but could be a collection as well


  "Value": {
            "_t": "System.Collections.Generic.List`1[System.String]",
            "_v": ["FileNumberOne.cs", "FileNumberTwo.cs"]
        }
    }],
    "Components": []
}

Идея вопроса / решения:

Итак, моя идея состояла в том, чтобы создать еще одно поле в документе, , в которое я бы бросил все «токены», которые я думаю он должен быть найден по.
Итак, все строки во всех соответствующих полях будут маркированы (разделены на PascalCase, дефисы, подчеркивания и т. д. c) и хранится в этом поле (например, search_data).

Затем я создам другой текстовый индекс , который будет смотреть только на поле search_data.

Соображения :

  1. Это сделает документы в два раза больше (почти все данные дублируется в поле search_data)
  2. Я не могу назначить веса токенам ... Если я не создаю несколько полей search_data с различными весами (которые будут содержать значения токенов, сгруппированные по релевантности)
  3. It все равно не решит проблему, если значение не может быть разбито на токены, например, если имя файла называется stackoverflowhackingattempt.cs, оно не будет разбито на токены и не будет найдено запросом 'hack' - если это не поиск по регулярному выражению.

Имеет ли этот подход смысл?
Кроме того, при таком подходе поиск в регулярных выражениях должен выполняться быстрее, чем в моем текущем? Я хотел бы знать, что вы, ребята, думаете, прежде чем я go впереди, и перепроектировать все это.
Приветствия!

...