Mongo - 如果子文档数组中的对象具有值,则添加字段

Posted

技术标签:

【中文标题】Mongo - 如果子文档数组中的对象具有值,则添加字段【英文标题】:Mongo - add field if object in array of sub docs has value 【发布时间】:2020-03-01 05:45:33 【问题描述】:

详情

我使用 express 开发调查应用程序,但在获取一些数据方面遇到了困难。

案例:

您可以通过“GET /surveys”获取所有调查。如果用户投票支持调查,则每个调查文档都必须包含hasVoted:mongoose.BooloptionsVote:mongoose.Map。 (SurveySchema 如下) 您可以通过“POST /surveys/vote”为调查投票 您可以看到任何调查的结果只有您投票支持它
 new Schema(
    question: 
        type: mongoose.Schema.Types.String,
        required: true,
    ,
    options: 
        type: [
            type: mongoose.Schema.Types.String,
            required: true,
        ]
    ,
    optionsVote: 
        type: mongoose.Schema.Types.Map,
        of: mongoose.Schema.Types.Number,
    ,
    votesCount: 
        type: mongoose.Schema.Types.Number,
    ,
    votes: 
        type: [
            user: 
                type: mongoose.Schema.Types.ObjectId,
                ref: 'User',
            ,
            option: mongoose.Schema.Types.Number,
        ]
    ,
)

目标:

所以问题的目标是如果votes数组中有“投票”子文档user===req.user.id,如何添加字段hasVotedoptionsVote


我相信你明白了,所以如果你知道如何更改架构以达到预期的结果,我愿意!


示例:

    数据:
[
 id:"surveyId1
 question:"Question",
 options:["op1","op2"],
 votes:[user:"userId1", option:0]
 votesCount:1,
 optionsVote:"0":1,"1":0
,
 id:"surveyId2
 question:"Question",
 options:["op1","op2"],
 votes:[user:"userId2", option:0]
 votesCount:1,
 optionsVote:"0":1,"1":0
]
    路由处理程序:

Where req.user.id='userId1' 然后进行 desired 查询。

    结果
[ // Voted for this survey
 id:"surveyId1
 question:"Question",
 options:["op1","op2"],
 votes:[user:"userId1", option:0]
 votesCount:1,
 optionsVote:"0":1,"1":0,
 hasVoted:true,
, // No voted for this survey
 id:"surveyId2
 question:"Question",
 options:["op1","op2"],
 votesCount:1,
]

【问题讨论】:

【参考方案1】:
    在MongoDB中,您可以按如下方式搜索子文档
//Mongodb query to search for survey filled by a user
db.survey.find( 'votes.user': myUserId )

因此,当您只能在用户投票的地方获得结果时,您真的需要hasVoted 字段吗?

    要拥有optionsVote 字段,首先我希望optionsVote 的架构为option: "a", count:1。您可以选择以下任何一种方法。

    A.通过增加POST /survey/vote 时投票选项的计数,设法在更新时更新optionsVote 字段。

    B.另一种方法是根据GET /survey 时的votes 条目计算optionsVote。你可以通过聚合来做到这一点

//Mongodb query to get optionsVote:option: "a", count:1 from votes:  user:"x", option:"a"
db.survey.aggregate([
     $unwind: "$votes" , 
     $group: 
        "_id":  "id": "_id", "option": "$votes.option" , 
       optionCount:  $sum: 1 
       
    ,
    
      $group:  "_id": "$_id.id" ,
      optionsVote:  $push :  option: "$_id.option", count: "$optionCount"  ,
      votes:  $push : '$votes'
    
])
//WARNING: I haven't tested this query, this is just to show the approach -> group based on votes.option and count all votes for that option for each document and then create optionsVote field by pushing all option with their count using $push into the field `optionsVote`

我推荐方法 A,因为我认为 POST 操作会比 GET 操作少得多。也更容易实现。话虽如此,将查询放在 B 方便将有助于您进行健全性检查。

【讨论】:

以上是关于Mongo - 如果子文档数组中的对象具有值,则添加字段的主要内容,如果未能解决你的问题,请参考以下文章

如何匹配 MongoDB 中的子文档数组?

如何匹配MongoDB中的子文档数组?

查看单个文档的数组时,mongoose .find() 没有结果

想要在 Mongo 中更新数组对象值的数组

Mongo使用Java通过数组对象字段值查询记录

合并数组中的两个对象,其中一个对象的键嵌套比另一个对象更深,位于 Mongo DB 的同一文档中