这是一个我认为可能会有所帮助的聚合......
db.collection.aggregate([
{ $project: { book: 1, author: 1, "book_words": { $split: [ "$book", " " ] }, "author_words": { $split: [ "$author", " " ] } } },
{ $project: { book:1, author: 1, "search_words": { $concatArrays: [ "$book_words", "$author_words" ] } } },
{ $match: { "search_words": { $all: [ "The", "King" ] } } },
{ $project: { "search_words": 0} }
]).pretty()
说明:
这个聚合有 4 个阶段...
- $项目
- $项目
- $匹配
- $项目
第一个 $project 会将字段“book”中的字符串值拆分为一个名为“book_words”的单词数组,并将字段“author”中的字符串值拆分为一个名为“author_words”的单词数组
第二个 $project 将两个新数组连接到一个名为“search_words”的数组中
$match 阶段过滤掉与搜索条件不匹配的记录
最后的 $project 阶段删除了名为“search_words”的临时数组字段
此聚合的结果文档看起来像...
{
"_id" : ObjectId("60d6139a9148371ae7d2b343"),
"book" : "The Stand",
"author" : "Stephen King"
}
{
"_id" : ObjectId("60d6139a9148371ae7d2b344"),
"book" : "The Dead Zone",
"author" : "Stephen King"
}
不区分大小写的匹配
为了提供不区分大小写的匹配,MongoDB 必须了解不区分大小写的含义。英文大小写不同于其他语言。因此,出于这个原因,我们必须添加一个索引,其排序规则将英语定义为语言,排序规则的强度为 2——这意味着英语不区分大小写。创建索引后,我们必须将排序规则作为聚合中的一个选项来引用。
创建索引
db.collection.createIndex( { book: 1, author: 1 }, { collation: { locale: 'en', strength: 2 } } )
这是两个字段的复合索引 - 'book' 和 'author'。注意此索引的排序选项...
使用排序规则进行聚合
现在索引以特定的排序规则存在,Mongo 现在可以计算不区分大小写的选项...
db.collection.aggregate([
{ $project: { book: 1, author: 1, "book_words": { $split: [ "$book", " " ] }, "author_words": { $split: [ "$author", " " ] } } },
{ $project: { book:1, author: 1, "search_words": { $concatArrays: [ "$book_words", "$author_words" ] } } },
{ $match: { "search_words": { $all: [ "the", "king" ] } } },
{ $project: { "search_words": 0} }
],
{ collation: { locale: "en", strength: 2 } }).pretty()
请注意,排序选项应用于聚合。此外,聚合 $match 阶段现在使用所有小写文本。
这是输出...
{
"_id" : ObjectId("60d6139a9148371ae7d2b343"),
"book" : "The Stand",
"author" : "Stephen King"
}
{
"_id" : ObjectId("60d6139a9148371ae7d2b344"),
"book" : "The Dead Zone",
"author" : "Stephen King"
}
小心
使用带有排序规则选项的正则表达式可能无法按预期工作,至少从索引策略的角度来看是这样。在我的示例中,我没有使用任何正则表达式 ($regex),因此它按预期工作。但同样,这是针对完全匹配,而不是部分匹配(也称为范围查询),例如“以 'ki*' 开头”
MongoDB Atlas 搜索
如果使用 MongoDB Atlas,则使用 Atlas Search 可以直接解决此问题,但省略了“the”等常用词。