由于对架构进行了一些更改,我不得不进行重构,这破坏了应用程序中的一个简单的 filter,在本例中是isToRead
,而其他一切都继续工作。
“资产”中应显示的文档是:
{
"_id": {
"$oid": "ID"
},
"userId": "ID",
"folderId": "ID",
"title": "Title",
"note": "<p><strong>Note.</strong></p>",
"typeOfAsset": "web",
"isFavourite": false,
"createdAt": {
"$date": {
"$numberLong": "1666702053399"
}
},
"updatedAt": {
"$date": {
"$numberLong": "1666702117855"
}
},
"isActive": 3,
"tags": [],
"traits": [
{
"$oid": "6357dae53298948a18a17c60"
}
]
"__v": 0
}
......我尝试筛选的“Assets_Traits”中的 * 参考 * 文档应为:
{
"_id": {
"$oid": "6357dae53298948a18a17c60"
},
"userId": "ID",
"numberOfViews": 1,
"isToRead": true,
"__v": 0
}
我将分享整个方法,其中包括各种尝试,无论出于什么原因,将不会工作。
let tags = args.tags ? args.tags.split(',') : []
let tagsToMatch = []
if (tags.length > 0) {
tags.forEach(tag => {
tagsToMatch.push(new mongoose.Types.ObjectId(tag))
})
}
let search = {
...(args.phraseToSearch.length > 0 && {
$search: {
index: 'assets',
compound: {
must: [{
phrase: {
query: args.phraseToSearch,
path: 'title',
slop: 2,
score: { boost: { value: 3 } }
}
}],
should: [{
phrase: {
query: args.phraseToSearch,
path: 'note',
slop: 2
}
}]
}
}
})
}
let project = {
$project: {
_id: 0,
id: '$_id',
userId: 1,
folderId: 1,
title: 1,
note: 1,
typeOfAsset: 1,
isFavourite: 1,
createdAt: 1,
updatedAt: 1,
isActive: 1,
attributes: 1,
preferences: 1,
// ...(args.typeOfAttribute === 'isToRead' && {
// traits: {
// $filter: {
// input: "$traits",
// cond: { $eq: [ "$$this.isToRead", true ] }
// }
// }
// }),
tags: 1,
traits: 1,
score: {
$meta: 'searchScore'
}
}
}
let match = {
$match: {
userId: args.userId,
typeOfAsset: {
$in: args.typeOfAsset === 'all' ? MixinAssets().all : [args.typeOfAsset] // [ 'file', 'folder', 'message', 'note', 'social', 'web' ]
},
...(tagsToMatch.length > 0 && {
tags: {
$in: tagsToMatch
}
}),
...(args.typeOfAttribute === 'isToRead' && {
// $expr: {
// $allElementsTrue: [{
// $map: {
// input: '$traits',
// as: 't',
// in: {
// $and: [
// { $eq: [ "$$t.userId", args.userId ] },
// { $eq: [ "$$t.isToRead", true ] }
// ]
// }
// }
// }]
// }
// $expr: {
// $filter: {
// input: "$traits",
// cond: {
// $and: [
// { $eq: [ "$$this.userId", args.userId ] },
// { $eq: [ "$$this.isToRead", true ] }
// ]
// }
// }
// }
}),
isActive: 3
}
}
let lookup = {}
switch (args.typeOfAttribute) {
case 'areFavourites':
match.$match.isFavourite = true
break
case 'isToRead':
// match.$match.traits = {
// userId: args.userId,
// isToRead: true
// }
// match.$match.traits = {
// $elemMatch: {
// userId: args.userId,
// isToRead: true
// }
// }
// lookup = {
// $lookup: {
// from: 'assets_traits',
// let: { isToRead: '$isToRead' },
// pipeline: [{
// $match: {
// $expr: {
// $eq: [ '$isToRead', true ]
// }
// },
// }],
// localField: 'userId',
// foreignField: 'userId',
// as: 'traits'
// }
// }
break
case 'inTrash':
match.$match.isActive = 2
break
}
let skip = {
$skip: args.skip
}
let limit = {
$limit: args.first
}
let group = {
$group: {
_id: null,
count: { $sum: 1 }
}
}
let sort = {
$sort: {
[args.orderBy]: args.orderDirection === 'asc' ? 1 : -1
}
}
console.info('Queries:getAllAssetsForNarrative()', match.$match)
let allAssets = await Models.Assets.schema.aggregate(
(search.hasOwnProperty('$search')) // Order of criteria is critical to the functioning of the aggregate method.
? [search, project, match, sort, skip, limit]
: [match, project, sort, skip, limit]
// : [match, project, { $unwind: '$traits' }, { $match: { traits: { $elemMatch: { isToRead: true } } } }, sort, skip, limit]
)
let [ totalNumberOfAssets ] = await Models.Assets.schema.aggregate(
(search.hasOwnProperty('$search')) // Order of criteria is critical to the functioning of the aggregate method.
? [search, project, match, group]
: [match, project, group]
// : [match, project, { $unwind: '$traits' }, { $match: { traits: { $elemMatch: { isToRead: true } } } }, group]
)
await (() => {
if (args.phraseToSearch.length > 0) {
const SearchFactory = require('../services/search/search')
const Search = SearchFactory(Models)
Search.insertRecentSearch({
userId: args.userId,
phraseToSearch: args.phraseToSearch.toLowerCase()
})
}
})()
我删除了聚合函数的最后两个数组中的lookup
,因为它变得太复杂了,我无法理解发生了什么。
奇怪的是,“标签”匹配,它也是一个 * 参考 *,而“资产_特质”不会返回或做任何事情。typeOfAsset
的值为:[ 'file', 'folder', 'message', 'note', 'social', 'web' ]
当选择“所有资产”时,选择“待读取”将针对所有类型的资产执行筛选,并且当选择特定类型的资产时,将发生附加筛选-如所解释的,这在更改架构之前起作用。
另外,忽略tags
,因为这里没有使用它们。
感谢您的想法!
1条答案
按热度按时间bnl4lu3b1#
你没有提供你的输入样本(参数)或你使用的常量(例如
MixinAssets().all
,我怀疑这是有问题的)。为了得到这个答案,我构建了自己的输入:
这会产生下列管缐(使用您的程式码):
正如您在Mongo Playground sample中所看到的,这是可行的。
那么你的问题是什么呢?正如我提到的,我怀疑一个问题是
MixinAssets().all
,如果args.typeOfAsset === 'all'
,那么你使用这个值,现在如果它是一个数组,匹配条件看起来像这样:这不会匹配任何内容,因为它是数组的数组,如果它是常量值,那么它也不会匹配,因为数据库中的类型不同。
我再给予你一个提示,通常当你想构建一个分页系统,需要results和totalResultCount时,通常使用$facet,这样你就不必执行两次管道,你就可以提高性能,如下所示:
Mongo Playground