春天数据MongoDb聚合查找级联。

问题描述 投票:1回答:1

我用的是 春天 (启动)2.2.7与 梦库 4.0运行在Debian Stretch(9.12)上.我设置了3个集合,我试图通过聚合查找级联操作加入。

  • 操作(Node类)
  • 股票
  • 目录

每个类都有一个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中(Spring-data-mongodb)我运行了

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.aggregation()指令中得到同样的空指针异常。


已解决

问题来自于SensorPersistenceService没有@自动连接MongoTemplate.根据帖子中给出的信息,不可能找到错误的原因,再次感谢@Valijon在这次任务中的帮助^^。

mongodb spring-boot aggregation-framework cascade lookup-tables
1个回答
0
投票

可能问题出在 NodeExpanded 期待单 ComponentProduct$lookup 聚合返回一个 array 两者都有。

如果您添加额外的 $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")
);
© www.soinside.com 2019 - 2024. All rights reserved.