我用的是 春天 (启动)2.2.7与 梦库 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中(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在这次任务中的帮助^^。
可能问题出在 NodeExpanded
期待单 Component
和 Product
但 $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")
);