从子集合中搜索包含来自父子集合的关键字
Posted
技术标签:
【中文标题】从子集合中搜索包含来自父子集合的关键字【英文标题】:search from child collection contains the keyword from parent and child collection 【发布时间】:2021-07-20 11:21:21 【问题描述】:我在使用父子关系集合从数据库获取数据时遇到问题。 这是我的收藏结构—— -邮政 ---发布布:品牌集合中的品牌ID -----品牌
现在我正在从 post 和 postcloth 中获取数据,如果 postcloth 和 brand 中的任何键匹配,则从 postcloth 和品牌表中进行关键字搜索。直到发布布料它与关键字搜索或条件一起工作正常,现在我还需要从品牌搜索并返回结果,如果关键字也包含在品牌中。 这是我的案例--
-
返回的数据:如果任何 post_cloths 键与搜索的关键字匹配
返回的数据:如果任何 post_cloths 键与关键字匹配或带有品牌名称的查找与关键字匹配
返回的数据:如果 post_cloths 中的所有键都与关键字不匹配,但带有品牌名称的查找与关键字匹配
数据未返回:如果 post_cloths 中没有与关键字匹配的键,并且查找品牌名称与关键字不匹配
这是我的代码:
var page = 0;
if (req.query.page >= 0)
page = req.query.page;
let filter = 'totalCloth': $gte: 1 ;
if (req.query.user != null && req.query.user != '')
filter.createdBy = ObjectID(req.query.user);
console.log(filter);
var searchQuery = [];
var brandSearchQuery = [];
if (req.query.keyword != null && req.query.keyword != '')
console.log(req.query.keyword);
keyword = req.query.keyword;
searchQuery = [
$regexFind:
input: '$category',
regex: new RegExp(keyword),
options: 'i',
,
,
$regexFind:
input: '$color',
regex: new RegExp(keyword),
options: 'i',
,
,
$regexFind:
input: '$country',
regex: new RegExp(keyword),
options: 'i',
,
,
$regexFind:
input: '$size',
regex: new RegExp(keyword),
options: 'i',
,
,
$regexFind:
input: '$clothMaterial',
regex: new RegExp(keyword),
options: 'i',
,
,
];
brandSearchQuery = [
$regexFind:
input: '$name',
regex: new RegExp(keyword),
options: 'i',
,
,
];
else
searchQuery = [];
brandSearchQuery = [];
// get the post details
// PostModel.find(filter).countDocuments().then(countPosts =>
PostModel.aggregate([
$lookup:
from: 'post_cloths',
let: postId: '$_id' ,
pipeline: [
//lookup for brand
$lookup:
from: 'brands',
let: brandId: '$brandId' ,
pipeline: [
$match:
$expr:
$and:
[
$eq: ['$_id', '$$brandId'] ,
$or: brandSearchQuery ,
],
,
,
,
],
as: 'brand',
,
,
//end of brand lookup
$match:
$expr:
$and:
[
$eq: ['$postId', '$$postId'] ,
$or: searchQuery,
,
],
,
,
,
$project:
totalBrands: $size: '$brand' ,
,
,
$match:
$expr:
$or: [ $match: totalBrands: $gte: 1 ] ,
,
,
],
as: 'postCloth',
,
,
$project:
image: 1,
createdAt: 1,
createdBy: 1,
mediaUrl:
$concat: [process.env.PROJECT_URL + '/files/', '$image'],
,
totalCloth: $size: '$postCloth' ,
,
,
//check for post cloth object if length is greater than equals to 1
$match: filter,
,
$skip: 12 * page ,
$limit: 12 ,
$sort: createdAt: -1 ,
]).exec(function(err, post)
return apiResponse.successResponseWithData(res, 'Successful', post);
);
我正在正确获取数据,但不是在从品牌搜索时。请建议我们如何从给定的案例中搜索数据。有简单的关键字搜索。
提前致谢
【问题讨论】:
发布所有集合和预期结果的一些示例文档。 这个太难理解了,能举例说明一下吗? 【参考方案1】:问题在于你是主要的$lookup
的管道:
首先你从brand
$lookup
开始,我假设它是有效的(如果你为你的集合提供架构,那将很容易验证),但是在$lookup
之后你这样做:
$match:
$expr:
$and:
[
$eq: ['$postId', '$$postId'] ,
$or: searchQuery,
,
],
,
,
,
这意味着如果searchQuery
失败,即使品牌存在,文档也会被过滤掉,您应该将其更改为:
$match:
$expr:
$and:
[
$eq: ['$postId', '$$postId'] ,
$or: [
$or: searchQuery
,
$gt: [$size: "$brand", 0]
],
,
],
,
,
,
现在这也将匹配在 brand
字段中包含任何品牌的文档,这意味着品牌与嵌套的 $lookup
匹配,然后您可以删除接下来检查品牌大小的 2 个阶段。
我还建议您将postId
的$eq
移动到$lookup
的开头,这将极大地提高性能,在所有更改之后整个管道看起来像这样:
PostModel.aggregate([
$lookup:
from: 'post_cloths',
let: postId: '$_id' ,
pipeline: [
$match: $eq: ['$postId', '$$postId'] ,
,
$lookup:
from: 'brands',
let: brandId: '$brandId' ,
pipeline: [
$match:
$expr:
$and:
[
$eq: ['$_id', '$$brandId'] ,
$or: brandSearchQuery ,
],
,
,
,
],
as: 'brand',
,
,
$match:
$expr:
$and:
[
$or: [
$or: searchQuery,
,
$gt: [ $size: '$brand' , 0],
,
],
,
],
,
,
,
],
as: 'postCloth',
,
,
$project:
image: 1,
createdAt: 1,
createdBy: 1,
mediaUrl:
$concat: [process.env.PROJECT_URL + '/files/', '$image'],
,
totalCloth: $size: '$postCloth' ,
,
,
$match: filter,
,
$skip: 12 * page ,
$limit: 12 ,
$sort: createdAt: -1 ,
])
【讨论】:
以上是关于从子集合中搜索包含来自父子集合的关键字的主要内容,如果未能解决你的问题,请参考以下文章