我目前正在开发一个项目,需要在1000毫秒内搜索(在本地计算机上)大型数据库(+25.000.000条记录)。这让我想到了MongoDB,可以达到理想的性能。我可以通过几种不同的索引来做到这一点,但是我需要能够部分匹配。
允许最终用户搜索几个字段。 (并非所有字段;需要能够搜索5/9的字段,其余的是无法为最终用户搜索的元数据)
我首先尝试为全文搜索创建复合索引(在所有5个字段上)
db.tracks.find({$text:{$search:"Greatest Hits"}})
这似乎运作得相当好,并且在任何复合领域给出了各种各样的结果,包括Great,Greatest和Hits。
但是,用户应该能够选择他想要搜索的字段。 (例如:AlbumTitle,TrackTitle等)。这意味着当切换曲目标题时,我不想要该列的结果。
db.tracks.find({AlbumTitle: "Greatest Hits"})
上面的查询将能够找到完全匹配,因此在搜索Greatest时找不到相同的结果。这让我想到了类似下面的内容
db.tracks.find({AlbumTitle: {$text: {$search: "Greatest Hits"}}})
但这并不起作用,因为那时$ text将是一个未知的运算符。
如果有类似上述内容的话,我可以根据切换字段动态构建我的查询,例如
db.tracks.find({$or: [ {ToggledField1: ...}, {ToggeldField4: ...} ]})
因此确保仅查询所需的字段。在MongoDB数据库中是否可以实现这一点,如果是这样,实现所需功能的最佳方法是什么
先谢谢
答案 0 :(得分:0)
最后我解决了它,如下所示
// Create an empty filter and make sure it is not null
var builder = Builders<Track>.Filter;
FilterDefinition<Track> filter = builder.Empty;
string[] searchWords = queryString.Split(' ');
if (ArtistChecked){
foreach (var words in searchWords){
//regex could be changed with options like ignore case
filter &= builder.Regex("Artist", BsonRegularExpression.Create(new System.Text.RegularExpressions.Regex(word)));
}
}
if (AlbumChecked){
foreach (var words in searchWords){
//regex could be changed with options like ignore case
filter &= builder.Regex("Album", BsonRegularExpression.Create(new System.Text.RegularExpressions.Regex(word)));
}
}
最后,您在MongoQuery中使用构建过滤器;可以在OR运算符中混合使用EQ来查询查询中的某些字段;但这样你就可以动态地构建查询。 当然,性能不如完全匹配(使用FullTextSearch),但这将使搜索方法变得可用。通过使用索引并说它以前缀
开头,性能可能更好如果该字段存在索引,则MongoDB会将正则表达式与索引中的值进行匹配,这可能比收集扫描更快。如果正则表达式是“前缀表达式”,则可以进一步优化,这意味着所有可能的匹配都以相同的字符串开头。这允许MongoDB从该前缀构造一个“范围”,并且仅匹配该范围内的索引中的那些值。
来源:https://docs.mongodb.org/manual/reference/operator/query/regex/#index-use
在我的情况下,这不会做,因为用户应该能够以他们想要的任何顺序输入搜索词;因为它只是出现在字段内部,所以无法保证使用正确的顺序。
打开以获取有关如何更快/更好的建议
P.S。有想法从MongoDB substring product search order by highest match
解决它