arrays - 参考文档上的MongoDB查询
问题描述
我在猫鼬中定义了两个模式,如下所示,
型号:文章
var articleSchema = new mongoose.Schema({
sequenceId: String
title: String,
abstract: String,
authors: [String],
date: Date,
words: [{
selectedWord: String,
details: { type: Schema.Types.ObjectId, ref: 'Word' }
}],
otherTags: [String]
})
型号:字
var wordSchema = new mongoose.Schema({
preferredWord: String,
synonyms: [String],
category: String
})
现在我试图获得以下场景的两组结果,
- 获取所有在selectedWord、preferredWord或同义词中具有 'wordAbc' 和/或 'wordXyz' 的文章
- 获取数据库中所有文章的selectedWord、preferredWord和同义词中的所有唯一词
使用猫鼬执行查询的最佳/有效方式是什么?
对于第一个结果,我尝试了部分查询,但收到 CastError 消息,
Article.find({})
.populate( 'words', null, { 'details': {$in: ['wordAbc', 'wordXyz']}} )
.exec(function(err, docs) {});
解决方案
我认为您可以使用聚合管道实现您想要的两件事。
- 获取所有在 selectedWord、preferredWord 或同义词中具有 'wordAbc' 和/或 'wordXyz' 的文章
首先,您需要填充数组details
字段中的所有单词words
,然后匹配基于selectedWord
,preferredWord
或的文章synonyms
。
这可以这样实现:
Article.aggregate([{
$unwind : {
path :"$words",
preserveNullAndEmptyArrays :true
}
},{
$lookup : {
from : "words",
localField : "words.details",
foreignField : "_id",
as : "words.details"
}
},{
$unwind : {
path : "$words.details",
preserveNullAndEmptyArrays : true
}
},{
$match : {
$or : [{
"words.selectedWord" : {$in: ['wordAbc', 'wordXyz']}
},{
"words.details.preferredWord" : {$in: ['wordAbc', 'wordXyz']}
},{
"words.details.synonyms" : {$in: ['wordAbc', 'wordXyz']}
}]
}
},{
$group : {
_id : "$_id",
title : {$first : "$title"},
abstract : {$first : "$abstract"},
authors : {$first : "$authors"},
date : {$first : "$date"},
words: {$push : "$words"},
otherTags: {$first : "$otherTags"}
}
}])
- 获取数据库中所有文章的 selectedWord、preferredWord 和同义词中的所有唯一词
在这种情况下,您必须先unwind
words
数组,然后populate
words.details
从words
集合,然后unwind
synonyms
数组,这样我们就可以创建一组selectedWord
,preferredWord
并synonyms
跨越所有articles
,最后在聚合管道的最后阶段制作一整套所有唯一词.
这可以这样实现:
Article.aggregate([{
$project : {
words : "$words"
}
},{
$unwind : "$words"
},{
$lookup : {
from : "words",
localField : "words.details",
foreignField : "_id",
as : "words.details"
}
},{
$unwind : "$words.details"
},{
$unwind : "$words.details.synonyms"
},{
$project : {
selectedWord : "$words.selectedWord",
preferredWord : "$words.details.preferredWord",
synonyms : "$words.details.synonyms"
}
},{
$group : {
_id : "null",
selectedWord : {$addToSet :"$selectedWord"},
preferredWord : {$addToSet :"$preferredWord"},
synonyms : {$addToSet :"$synonyms"}
}
},{
$project : {
commonWords : {$setUnion : ["$selectedWord","$preferredWord","$synonys"]}
}
}])
第二次聚合的解释。
$project
: 我们只想要单词,所以我保留了所有文章的单词字段,并从管道中删除了所有其他不必要的字段。$unwind
:我们需要展开 words 数组,以便我们可以在管道的下一阶段从 words 集合中 $lookup words.details$lookup
:从单词集合中填充详细信息。$unwind
:由于$lookup
返回一个数组,我们需要展开它以使其成为一个对象$unwind
: unwindwords.details.synonyms
,以便我们可以将它们分组并在管道的下一阶段创建唯一单词数组,在此阶段,聚合管道中的单个文档将如下所示:{ words : { selectedWord :"someword", details : { preferredWord : "otherword", synonym : "synonymword" } } }
$project
: 我们需要这个扁平化的对象结构。在此阶段之后,管道中的单个文档将如下所示:{ selectedWord :"someword", preferredWord : "otherword", synonym : "synonymword" }
$group
: 将所有的合selectedWord
为一个数组,合preferredWord
为一个数组,同义词合为一个数组,$addToSet 用于删除重复对象$project
:组合所有 3 个数组并创建一组唯一单词
有关 mongoDB 使用的所有运算符的详细信息,请阅读相应的文档。
我希望这可以帮助你