Mongodb查询参考文件

时间:2019-03-13 19:44:05

标签: arrays node.js mongodb mongoose

我在猫鼬中定义了以下两个模式,

型号:文章

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]
})

型号:Word

var wordSchema = new mongoose.Schema({
    preferredWord: String,
    synonyms: [String],
    category: String
})

现在我正尝试在以下情况下获得2组结果,

  1. 获取所有在 selectedWord preferredWord 同义词
  2. 中具有“ wordAbc”和/或“ wordXyz”的文章
  3. 获取数据库中所有文章中的 selectedWord preferredWord 同义词中的所有唯一词

使用猫鼬执行查询的最佳/有效方式是什么?

对于第一个结果,我尝试了部分查询,但收到了CastError消息,

Article.find({})
.populate( 'words', null, { 'details': {$in: ['wordAbc', 'wordXyz']}} )
.exec(function(err, docs) {});

1 个答案:

答案 0 :(得分:2)

我认为您可以使用聚合管道来实现您想要的所有事情。

  
      
  1. 获取所有包含“ wordAbc”和/或“ wordXyz”的文章   selectedWord,preferredWord或同义词
  2.   

首先,您需要填充details数组的words字段中的所有单词,然后根据selectedWordpreferredWord或{{1}匹配文章}。

可以这样实现:

synonyms
  
      
  1. 获取selectedWord,preferredWord和同义词中的所有唯一单词   数据库中的所有文章
  2.   

在这种情况下,您将必须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"} } }]) unwind数组,然后words集合中的populate words.details,然后words {{ 1}}数组,以便我们可以在所有unwind上创建synonymsselectedWordpreferredWord的集合,然后最终形成所有唯一的集合聚合管道最后阶段的单词。

可以这样实现:

synonyms

第二次汇总的说明。

  1. articles:我们只需要单词,所以我继续所有文章的单词字段,并从管道中删除了所有其他不必要的字段。
  2. 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"]} } }]) :我们需要展开单词数组,以便我们可以在下一阶段的管道中$ lookup words.details来自单词收集的详细信息
  3. $project:从单词收集中填充详细信息。
  4. $unwind:由于$lookup返回一个数组,我们需要对其进行展开以使其成为对象
  5. $unwind:展开$lookup,以便我们可以将它们分组并在管道的下一阶段中创建唯一的单词数组,在这一阶段,聚合管道中的各个文档看起来像这个:

    $unwind
  6. words.details.synonyms:我们需要使对象结构扁平化。在此阶段之后,管道中的单个文档将如下所示:

    {
        words : {
            selectedWord :"someword",
            details : {
                preferredWord : "otherword",
                synonym : "synonymword"
            }
        }
    }
    
  7. $project:将所有{ selectedWord :"someword", preferredWord : "otherword", synonym : "synonymword" } 组合成一个数组,$group组合成一个数组,并将同义词组合成一个数组,$ addToSet用于删除重复的对象

  8. selectedWord:组合所有3个数组并创建一个唯一单词数组

有关mongoDB使用的所有运算符的详细信息,请阅读相应的文档。

$setUnion documentation

$addToSet documentation

$project documentation

$unwind documentation

Documentation of all the operators of mongodb aggregation pipeline

希望这对您有所帮助