java - MongoDB java API 聚合 $lookup 和管道使用变量

标签 java mongodb aggregate

我有 2 个集合假设为 1 对多关系,例如用户和评论。要求是将用户与其最新评论合并为单个对象,并返回新合并对象的列表作为结果。

聚合在 mongo 控制台中完美运行

db.user.aggregate(
        {
            $addFields:{
                cId: {$toString: '$_id'},
                user: '$$ROOT'
            }
        },
        {$match: {'invitees': {$elemMatch: {'user.userId': '5e70e82532044a5e4e7cbc8d'}}}},
        {$lookup: {
                from: 'comment',
                let: {'cc': '$cId'},
                pipeline: [
                    {$match: {$expr: {$and: [{$eq: ['$$cc', '$userId']},{$gte: ['$time', '$$NOW']}]}}},
                    {$sort: {'time': -1}},
                    {$limit: 1}
                ],
                as: 'next'
            }
        },
        {$unwind: {path: '$next'}},
        {
            $project: {
                _id: 0,
                user: 1,
                next: 1,
                status: {
                    $map: {
                        input: {
                            $filter: {
                                input: '$invitees',
                                as: 'item',
                                cond: {
                                    $eq: ['$$item.user.userId', '$userId']
                                }
                            }
                        },
                        as: 'invitee',
                        in: '$$invitee.status'
                    }
                }
            }
        },
        {$unwind: {path: '$status'}},
        {$match: {$expr: {$in: ['$status', ['Accepted', 'Pending']]}}},
        {$sort: {status: 1}}
        )

我试着把它翻译成 Spring 数据聚合但 $toString 有问题。然后我尝试使用 mongodb java API Aggregations API 来运行它。
Arrays.asList(
        Aggregates.addFields(Arrays.asList(
            new Field<>("cId", Document.parse("{$toString: '$_id'}")),
            new Field<>("user", "$$ROOT"),
            new Field<>("userId", userId)
            )
        ),
        Aggregates.match(Filters.elemMatch("invitees", Filters.eq("user.userId", userId))),
        Aggregates.lookup(
            "comment",
            Collections.singletonList(new Variable<>("cc", "$cId")),
            Arrays.asList(
                Aggregates.match(
                    Filters.expr(
                        Filters.and(
                            Filters.eq("$$cc", "$userId")
                        ))),
                Aggregates.sort(Sorts.ascending("time")),
                Aggregates.limit(1)
            ),
            "next"
        )
    );

    AggregateIterable<Document> r = mongoClient
        .getDatabase("my-db")
        .getCollection("user")
        .aggregate(l);

接收错误:
Command failed with error 168 (InvalidPipelineOperator): 'Unrecognized expression '$$cc'' on server localhost:27017. The full response is {"ok": 0.0, "errmsg": "Unrecognized expression '$$cc'", "code": 168, "codeName": "InvalidPipelineOperator"}

使用:
    <dependency>
      <groupId>org.mongodb</groupId>
      <artifactId>mongodb-driver</artifactId>
      <version>3.12.3</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.mongodb/mongodb-driver-core -->
    <dependency>
      <groupId>org.mongodb</groupId>
      <artifactId>mongodb-driver-core</artifactId>
      <version>3.12.3</version>
    </dependency>


    <dependency>
      <groupId>org.mongodb</groupId>
      <artifactId>bson</artifactId>
      <version>3.12.3</version>
    </dependency>
  • java版本:8
  • mongod 版本:4.2.2
  • mongo shell 版本:4.2.3

  • 任何建议都非常感谢。

    最佳答案

    我以为关键是Filters.eq无法读取前缀为 $ 的变量, 喜欢 $$cc$userId .我尝试重写这部分,它可以工作。

    Aggregates.match(
        Filters.expr(
            Filters.and(
                 new Document("$eq", Arrays.asList("$userId", "$$cc"))
            )
        )
    )
    

    关于java - MongoDB java API 聚合 $lookup 和管道使用变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61484933/

    相关文章:

    r - 根据多个引用日期计算每个客户的事件发生次数

    postgresql - DDD : modelling aggregate entities' unique global/local id in PostgreSQL

    java - FairSync 能保证执行顺序吗?

    java - AutowireCapableBeanFactory.autowireBean(bean) 从不调用 InitlizingBean.afterPropertiesSet()?

    java - 如何在日期解析(Java)中忽略时区标识符?

    javascript - 如何通过对象 ID 访问其他属性值?

    java - 创建一个新对象以避免空指针异常是否正确?

    mongodb - 使用 Helm 在 Kubernetes 中安装 Mongodb

    javascript - 删除父文档时 Mongoose 删除子文档引用

    postgresql - 修改postgresql "list"聚合去重