Справочная информация:
Я работаю над сторонним проектом с открытым исходным кодом, который использует 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.
Соображения :
- Это сделает документы в два раза больше (почти все данные дублируется в поле search_data)
- Я не могу назначить веса токенам ... Если я не создаю несколько полей search_data с различными весами (которые будут содержать значения токенов, сгруппированные по релевантности)
- It все равно не решит проблему, если значение не может быть разбито на токены, например, если имя файла называется stackoverflowhackingattempt.cs, оно не будет разбито на токены и не будет найдено запросом 'hack' - если это не поиск по регулярному выражению.
Имеет ли этот подход смысл?
Кроме того, при таком подходе поиск в регулярных выражениях должен выполняться быстрее, чем в моем текущем? Я хотел бы знать, что вы, ребята, думаете, прежде чем я go впереди, и перепроектировать все это.
Приветствия!