当前位置: 首页 > 知识库问答 >
问题:

Spring数据MongoDb聚合查找级联

郑桐
2023-03-14

我使用Spring(引导)2.2.7与mongoDB 4.0运行在Debian Stretch(9.12)。我已经设置了3个集合,我试图通过聚合查找级联操作加入这些集合。

  • 操作(节点类)
  • 股票(组件类)
  • 目录(产品类)

每个类都有一个将它们链接在一起的uuid字符串属性。

节点(传感器、接收器、基站等)

@Document(collection = "operations")
public class Node implements Serializable {
    @Id
    private String _id;
    private String componentUuId;
....
}

组件(带有序列号、条形码的交付产品…)

@Document(collection = "stock")
public class Component implements Serializable {
    @Id
    private String _id;
    private String uuId;
    private String productUuId;
....
}

产品(市场人工制品)

@Document(collection = "catalog")
public class Product implements Serializable {
    @Id
    private String _id;
    private String uuId;
....
}

在mongo shell中运行此命令时:

db.operations.aggregate([
   {
     $lookup: {
         "from": "stock",
         "localField": "componentUuId",
         "foreignField": "uuId",
         "as": "component"
     }
   },
   {
     $lookup: {
         "from": "catalog",
         "localField": "component.productUuId",
         "foreignField": "uuId",
         "as": "product"
     }
   }
]).pretty()

我明白了

{
    "_id" : ObjectId("5ec952a7714e7e248b5fb98b"),
    "uuId" : "3b5e3417-166c-4d69-9fa5-b0856d819541",
    "componentUuId" : "57eff5c5-8b3c-43cb-9f2d-1c4098fc0c1f",
    "component" : [
        {
            "_id" : ObjectId("5ec952a4714e7e248b5fb97f"),
            "uuId" : "57eff5c5-8b3c-43cb-9f2d-1c4098fc0c1f",
            "productUuId" : "3da7a6a6-ccf6-4fe1-892a-a6d6b82396c1",
            "created" : ISODate("2020-05-23T14:43:16.588Z"),
            "_class" : "org.open_si.udc_common.models.Component"
            .......
        }
    ],
    "product" : [
        {
            "_id" : ObjectId("5ec952a1714e7e248b5fb969"),
            "uuId" : "3da7a6a6-ccf6-4fe1-892a-a6d6b82396c1",
            "model" : "TMP36GT9Z",
            "_class" : "org.open_si.udc_common.models.Product"
            ......
        }
    ]
}

因此,为了在Java中实现同样的目标,我运行了

Aggregation agg = Aggregation.newAggregation(
    Aggregation.lookup(mongoTemplate.getCollectionName(Component.class),
        "componentUuId", "uuId", "component"),
    Aggregation.lookup(mongoTemplate.getCollectionName(Product.class),
        "component.productUuId", "uuId", "product")
);

AggregationResults<NodeExpanded> results = mongoTemplate.aggregate(agg, mongoTemplate.getCollectionName(Node.class), NodeExpanded.class);

return results.getMappedResults();

使用NodeExpanded类

public class NodeExpanded implements Serializable {

    private String uuId;
    private Component component;
    private Product product;
....
}

注意:我没有扩展Node基类,因为在下面的问题之前我得到了一个重复的密钥错误。

问题是,我在托管该代码的服务中遇到了一个错误:

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause

java.lang.NullPointerException: null

不幸的是,我不知道如何在Spring的较低级别进行调试,也无法找出最初的错误是什么。

请注意,让产品链接到组件的代码如下:

Aggregation agg = Aggregation.newAggregation(
                Aggregation.lookup(mongoTemplate.getCollectionName(Product.class),
                        "productUuId", "uuId", "product")
        );

AggregationResults<ComponentExpanded> results =
                mongoTemplate.aggregate(agg,mongoTemplate.getCollectionName(Component.class), ComponentExpanded.class);
return results.getMappedResults();

随着扩展类:

public class ComponentExpanded implements Serializable {
    private String uuId;
    private Product product;
...
}

有什么想法吗?提前谢谢。

编辑

为了更深入地调试,我限制了代码只能将操作集合(Node.class)连接到库存(Component.class),就像我对库存(Component.class)和目录(Product.class)工作正常。

public List<NodeExpanded> list() {

    Aggregation agg = Aggregation.newAggregation(
            Aggregation.lookup(mongoTemplate.getCollectionName(Component.class),
                    "componentUuId", "uuId", "component")

    );

    AggregationResults<NodeExpanded> results = mongoTemplate.aggregate(agg, mongoTemplate.getCollectionName(Node.class), NodeExpanded.class);
    return results.getMappedResults();
}

使用一个简单的NodeExpanded类作为

public class NodeExpanded implements Serializable {

    private String uuId;
    private Component component;

}

我在mongoTemplate上得到了相同的空指针异常。聚合()指令

解决了的

问题来自SensorPersistenceService,它没有@Autowired MongoTemplate。根据那篇文章中给出的信息,不可能找出错误原因。再次感谢@Valijon在这次任务中的帮助^^

共有1个答案

邵兴文
2023-03-14

可能问题是NodeExpanded期望单个Component和Products,但是$lookup聚合返回两个的数组

如果您添加额外的$project阶段,它应该可以解决您的问题。

Aggregation agg = Aggregation.newAggregation(
    Aggregation.lookup(mongoTemplate.getCollectionName(Component.class), 
        "componentUuId", "uuId", "component"),
    Aggregation.lookup(mongoTemplate.getCollectionName(Product.class), 
        "component.productUuId", "uuId", "product"),
    Aggregation.project()
        .andInclude("uuId") //put here all fields for NodeExpanded
        .and(ArrayOperators.ArrayElemAt.arrayOf("component").elementAt(0)).as("component")
        .and(ArrayOperators.ArrayElemAt.arrayOf("product").elementAt(0)).as("product")
);
 类似资料:
  • 有人能帮我把这个mongoDB聚合转换成Spring数据mongo吗? 我试图在每个邀请函文件中获得未提醒与会者的电子邮件列表。 让它在mongo shell中运行,但需要在Spring data mongo中运行。 我的shell查询 ) 正如你们所看到的,这是我提出的,它在管道的项目和团队运作中并没有像预期的那样发挥作用。下面给出了生成的查询。 聚合对象创建 它创建以下查询 聚合对象生成的查询

  • 我在mongodb 4.0中使用Spring(boot)数据2.2.7。我已经设置了3个集合,试图通过聚合查找操作加入这些集合。 目录 股票 操作 目录 映射由 股票 映射由 productId字段引用目录集合中的_id字段 操作 映射由 组件ID字段指的是库存集合中的_id 我想查询操作或库存收集,以检索相应的节点或组件对象列表,该列表由Product.model字段(在目录集合中)排序。) 虽

  • 有人知道如何使用Spring-Data将下面的聚合函数转换成java代码吗?

  • 我的应用程序使用Spring数据MongoDB,我试图在嵌入式文档中按降序排序数据,这是不工作的。 请参考以下JSON文档 JSON-库存文件: Spring数据Mongodb聚合查询: 电流输出: 苹果:150.0 李子:200.0 橙子:500.0 预期产量(按需求描述订单): 橙子:500.0 李子:200.0 苹果:150.0 你能帮我按降序得到预期的输出吗? 此外,我计划通过使用上述带限

  • 但在我看来不对。有人能建议别的方法做这件事吗。

  • 我有包含以下模式的文档的集合。我想过滤/查找所有包含性别女性的文档并汇总大脑评分的总和。我尝试了下面的语句,它显示了无效的管道错误。 架构: