MONGODB 全文搜索逻辑或查询
MONGODB Full Text Search Logical OR Query
我目前正在开展一个项目,需要在 1000 毫秒内(在本地计算机上)搜索大型数据库(+25.000.000 条记录)。这让我想到了 MongoDB 并且可以达到所需的性能。我可以通过几种不同类型的索引来做到这一点,但是我需要能够部分匹配。
允许最终用户在几个字段上进行搜索。 (不是所有字段;需要能够搜索 5/9 的字段,其余是最终用户无法搜索的元数据)
我首先尝试为全文搜索创建复合索引(在所有 5 个字段上)
db.tracks.find({$text:{$search:"Greatest Hits"}})
这似乎工作得很好,并在任何复合字段上为我提供了 Great、Greatest 和 Hits 的各种结果。
但是,用户应该能够 select 他想要搜索的字段。 (例如: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 数据库中完全可行吗?如果可以,实现所需功能的最佳方法是什么
提前致谢
最后我按照下面的方法解决了
// 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-Operators 并对查询中的某些字段使用 EQ;但这样你就可以动态构建查询。
当然,性能不如完全匹配(使用 FullTextSearch),但这将使所需的搜索方法可用。通过使用索引并说它以 prefix
开头,性能可能会更好
If an index exists for the field, then MongoDB matches the regular expression against the values in the index, which can be faster than a collection scan. Further optimization can occur if the regular expression is a “prefix expression”, which means that all potential matches start with the same string. This allows MongoDB to construct a “range” from that prefix and only match against those values from the index that fall within that range.
来源:https://docs.mongodb.org/manual/reference/operator/query/regex/#index-use
在我的例子中,这是行不通的,因为用户应该能够以他们想要的任何顺序输入搜索词;并且由于它必须出现在字段内部,因此无法保证使用正确的顺序。
欢迎提出如何制作这个的建议faster/better
P.S。从 MongoDB substring product search order by highest match
得到解决问题的想法
我目前正在开展一个项目,需要在 1000 毫秒内(在本地计算机上)搜索大型数据库(+25.000.000 条记录)。这让我想到了 MongoDB 并且可以达到所需的性能。我可以通过几种不同类型的索引来做到这一点,但是我需要能够部分匹配。
允许最终用户在几个字段上进行搜索。 (不是所有字段;需要能够搜索 5/9 的字段,其余是最终用户无法搜索的元数据)
我首先尝试为全文搜索创建复合索引(在所有 5 个字段上)
db.tracks.find({$text:{$search:"Greatest Hits"}})
这似乎工作得很好,并在任何复合字段上为我提供了 Great、Greatest 和 Hits 的各种结果。
但是,用户应该能够 select 他想要搜索的字段。 (例如: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 数据库中完全可行吗?如果可以,实现所需功能的最佳方法是什么
提前致谢
最后我按照下面的方法解决了
// 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-Operators 并对查询中的某些字段使用 EQ;但这样你就可以动态构建查询。 当然,性能不如完全匹配(使用 FullTextSearch),但这将使所需的搜索方法可用。通过使用索引并说它以 prefix
开头,性能可能会更好If an index exists for the field, then MongoDB matches the regular expression against the values in the index, which can be faster than a collection scan. Further optimization can occur if the regular expression is a “prefix expression”, which means that all potential matches start with the same string. This allows MongoDB to construct a “range” from that prefix and only match against those values from the index that fall within that range.
来源:https://docs.mongodb.org/manual/reference/operator/query/regex/#index-use
在我的例子中,这是行不通的,因为用户应该能够以他们想要的任何顺序输入搜索词;并且由于它必须出现在字段内部,因此无法保证使用正确的顺序。
欢迎提出如何制作这个的建议faster/better
P.S。从 MongoDB substring product search order by highest match
得到解决问题的想法