背景:
我正在开发一个使用 Mongo 作为数据库的开源 side-project-for-fun。该项目应该是一个“存储库目录”。
它应该收集有关数百/数千个软件项目的数据 - 基本信息,例如名称、描述、一些标签以及其中的文件列表。下面的示例文档。
要求:
拥有目录的主要目的是它可以轻松可靠地搜索,并且还应该依赖“部分匹配”。
因此,例如,如果一个项目名为“XmlValidator”,我应该能够通过“Xml”搜索字符串找到它。
如果一个项目包含一个名为“GoogleDriveSynchronizer.cs”的文件,我应该能够通过“Google”或“GoogleDrive”等找到它。
这不是开箱即用的。
搜索也应该很快。
在大小方面,实际上,我不希望超过 10000 个文档,平均文档大小为 2kb,但假设我希望它即使在平均大小为 3kb 的 100k 文档中也能表现良好。由于性能原因,我不考虑正则表达式搜索(虽然我不确定,也许 3KB 的 100k 文档不难扫描?)
现在的情况:
我的文本索引目前设置如下(几乎大部分字段,但不是全部):
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、连字符、下划线等拆分)并存储在该字段中(例如 search_data)。
然后我会创建一个不同的文本索引,它只会查看 search_data 字段。
考虑因素是:
- 这将使文档大两倍(几乎所有数据都将在 search_data 字段中重复)
- 我无法为标记分配权重...除非我创建多个具有不同权重的 search_data 字段(其中将包含按相关性分组的标记化值)
- 如果无法对值进行标记,它仍然无法解决问题,例如,如果文件名称为“stackoverflowhackingattempt.cs”,它将不会被标记并且无法通过“hack”查询找到 - 除非它是正则表达式搜索.
这种方法有意义吗?
此外,使用这种方法,正则表达式搜索是否应该比我目前的搜索执行得更快?在我继续重新设计整个事情之前,我想知道你们的想法。
干杯!