首页 > 解决方案 > 参考文档上的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
})

现在我试图获得以下场景的两组结果,

  1. 获取所有在selectedWordpreferredWord同义词中具有 'wordAbc' 和/或 'wordXyz' 的文章
  2. 获取数据库中所有文章的selectedWordpreferredWord同义词中的所有唯一词

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

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

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

标签: arraysnode.jsmongodbmongoose

解决方案


我认为您可以使用聚合管道实现您想要的两件事。

  1. 获取所有在 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"}
    }
}])
  1. 获取数据库中所有文章的 selectedWord、preferredWord 和同义词中的所有唯一词

在这种情况下,您必须先unwind words数组,然后populate words.detailswords集合,然后unwind synonyms数组,这样我们就可以创建一组selectedWord,preferredWordsynonyms跨越所有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"]}
    }
}])

第二次聚合的解释。

  1. $project: 我们只想要单词,所以我保留了所有文章的单词字段,并从管道中删除了所有其他不必要的字段。
  2. $unwind:我们需要展开 words 数组,以便我们可以在管道的下一阶段从 words 集合中 $lookup words.details
  3. $lookup:从单词集合中填充详细信息。
  4. $unwind:由于$lookup返回一个数组,我们需要展开它以使其成为一个对象
  5. $unwind: unwind words.details.synonyms,以便我们可以将它们分组并在管道的下一阶段创建唯一单词数组,在此阶段,聚合管道中的单个文档将如下所示:

    {
        words : {
            selectedWord :"someword",
            details : {
                preferredWord : "otherword",
                synonym : "synonymword"
            }
        }
    }
    
  6. $project: 我们需要这个扁平化的对象结构。在此阶段之后,管道中的单个文档将如下所示:

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

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

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

$setUnion 文档

$addToSet 文档

$项目文档

$unwind 文档

mongodb聚合管道所有算子的文档

我希望这可以帮助你


推荐阅读