MongoDB:匹配对象数组的对象不等于给定值的文档

gopyfrb3  于 2023-04-29  发布在  Go
关注(0)|答案(1)|浏览(136)

以下是我的数据库,只有相关字段:

[
  {
    _id: ObjectId('641b5665894f755f6dc422a2'),
    directMsgs: {
      person1: [
        {
          authorId: ObjectId('6454bb4e33b90133ba752e96'),
          isRead: false
        },
        {
          authorId: ObjectId('641b5665894f755f6dc422a2'),
          isRead: true
        }
      ],
      person2: [
        {
          authorId: ObjectId('641b5665894f755f6dc422a2'),
          isRead: true
        },
        {
          authorId: ObjectId('642b5765834f755f6dc422b3'),
          isRead: true
        }
      ]
    }
  }
]

下面是投影后的样子:

[
  {
    _id: ObjectId('641b5665894f755f6dc422a2'),
    directMsgs: [
      {
        k: 'person1',
        v: [
          {
            authorId: ObjectId('6454bb4e33b90133ba752e96'),
            isRead: false
          },
          {
            authorId: ObjectId('641b5665894f755f6dc422a2'),
            isRead: true
          }
        ],
      },
      {
        {
          k: 'person2',
          v: [
            {
              authorId: ObjectId('641b5665894f755f6dc422a2'),
              isRead: true
            },
            {
              authorId: ObjectId('642b5765834f755f6dc422b3'),
              isRead: true
            }
          ]
        }
      }
    ]
  }
]

我希望能够检查一个用户是否有任何未读消息,其中消息的authorId不等于用户的_id。以下是我尝试过的:

const userId = '641b5665891f755f6dd422a2'
const uid = new ObjectId(userId)

const data = await User.aggregate(
    [
        {
            $project: { 
                directMsgs: { $objectToArray: '$directMsgs'} 
            }
        },
        { 
            $match: { 
                _id: uid, 
                'directMsgs.v.authorId': { $ne: uid }, 
                'directMsgs.v.isRead': false 
            }
        }
    ]
)

匹配似乎没有这行也能正常工作:'directMsgs.v.authorId': { $ne: uid }。如果我将其更改为'directMsgs.v.authorId': uid,它将与您所期望的匹配。$ne操作员似乎有问题。你们会在这里干什么?

piok6c0g

piok6c0g1#

来自MongoDB $match文档
$match接受指定查询条件的文档。查询语法与读取操作查询语法相同;即$match不接受原始聚合表达式。相反,使用$expr查询表达式将聚合表达式包含在$match中。
当您尝试在$match阶段使用运算符实现过滤时,查询不起作用:

'directMsgs.v.authorId': { $ne: uid }

您应该使用$expr运算符。
$match载物台

  1. $and-过滤匹配多个条件的文档。
    1.1.按_id匹配文档
    1.2. $ne-比较 1的结果。2.1 不是空数组。
    1.2.1 $filter-过滤数组中的文档。
    input-$reduce-将嵌套数组directMsgs.v展平为一级数组。
    cond-通过authorId不等于uidisRead等于false匹配文档。
db.collection.aggregate([
  {
    $project: {
      directMsgs: {
        $objectToArray: "$directMsgs"
      }
    }
  },
  {
    $match: {
      $expr: {
        $and: [
          {
            _id: uid
          },
          {
            $ne: [
              {
                $filter: {
                  input: {
                    $reduce: {
                      input: "$directMsgs.v",
                      initialValue: [],
                      in: {
                        $concatArrays: [
                          "$$value",
                          "$$this"
                        ]
                      }
                    }
                  },
                  cond: {
                    $and: [
                      {
                        $ne: [
                          "$$this.authorId",
                          uid
                        ]
                      },
                      {
                        $eq: [
                          "$$this.isRead",
                          false
                        ]
                      }
                    ]
                  }
                }
              },
              []
            ]
          }
        ]
      }
    }
  }
])

Demo @ Mongo Playground

相关问题