在Atlas Search中同时搜索嵌入字段与非嵌入字段的问题
解决方案
问题出在你的$search阶段仅针对嵌入文档todos进行查询,没有包含根级的title字段。需要调整$search的结构,用compound操作符同时包含对title和todos.todo的搜索逻辑。
修改后的聚合管道中$search部分核心调整如下:
{ $search: { index: 'search_todos', compound: { should: [ // 新增针对title字段的搜索逻辑 { text: { query: search, path: 'title', fuzzy: { maxEdits: 1, maxExpansions: 10, }, }, }, { phrase: { query: search, path: 'title', slop: 2, }, }, // 保留原有的嵌入文档todos查询逻辑 { embeddedDocument: { path: 'todos', operator: { compound: { must: [ { text: { query: search, path: ['todos.todo'], fuzzy: { maxEdits: 1, maxExpansions: 10, }, }, }, ], should: [ { phrase: { query: search, path: ['todos.todo'], slop: 2, }, }, ], }, }, }, }, ], }, count: { type: 'total', }, }, }
关键修改说明:
- 外层改用
compound操作符,通过should数组同时容纳两类搜索条件:- 新增与
todos.todo逻辑一致的title字段查询(text模糊匹配+phrase短语匹配) - 将原有的嵌入文档查询作为
should数组的一个元素保留
- 新增与
should规则表示只要匹配任意一个条件,文档就会被返回,且会根据匹配条件的数量计算相关性得分
完整的聚合管道代码:
const searchtodos = await this.todoModel.aggregate([ { $search: { index: 'search_todos', compound: { should: [ { text: { query: search, path: 'title', fuzzy: { maxEdits: 1, maxExpansions: 10, }, }, }, { phrase: { query: search, path: 'title', slop: 2, }, }, { embeddedDocument: { path: 'todos', operator: { compound: { must: [ { text: { query: search, path: ['todos.todo'], fuzzy: { maxEdits: 1, maxExpansions: 10, }, }, }, ], should: [ { phrase: { query: search, path: ['todos.todo'], slop: 2, }, }, ], }, }, }, }, ], }, count: { type: 'total', }, }, }, { $match: query, }, { $lookup: { from: 'userentities', localField: 'userId', foreignField: '_id', as: 'userData', }, }, { $unwind: '$userData', }, { $project: todoProject, }, { $facet: { totalCount: [{ $count: 'count' }], documents: [ { $skip: (page - 1) * limit, }, { $limit: limit, }, ], }, }, ]);
修改后,搜索"Demo"会匹配title字段,搜索"football"会匹配todos.todo字段,两种场景都能返回对应文档。
内容的提问来源于stack exchange,提问作者zackOverflow
相关产品推荐
相关产品推荐

