我使用的是Spring (boot) data 2.2.7和mongodb 4.0。我设置了3个集合,试图通过聚合查找操作加入。
目录
{
"_id" : ObjectId("5ec7856eb9eb171b72f721af"),
"model" : "HX711",
"type" : "DIGITAL",
....
}
映射
@Document(collection = "catalog")
public class Product implements Serializable {
@Id
private String _id;
@TextIndexed
private String model;
....
库存
{
"_id" : ObjectId("5ec78573b9eb171b72f721ba"),
"serialNumber" : "7af646bb-a5a8-4b86-b56b-07c12a625265",
"bareCode" : "72193.67751691974",
"productId" : "5ec7856eb9eb171b72f721af",
......
}
映射
@Document(collection = "stock")
public class Component implements Serializable {
@Id
private String _id;
private String productId;
....
的 产品ID 字段指的是 身份证 一本
业务
{
"_id" : ObjectId("5ec78671b9eb171b72f721d3"),
"componentId" : ""5ec78573b9eb171b72f721ba",
.....
}
映射
public class Node implements Serializable {
@Id
private String _id;
private String componentId;
....
的 组件ID 字段指的是 身份证 储备品
我想查询 业务 或 库存 集合来检索按Product.model字段排序的相应节点或组件对象列表(在 目录 集合)。)
虽然我们的目标是用Java编写代码,但我尝试着先在 芒果壳 但我甚至不能让它工作,因为我试图用ObjectId连接(查找)一个字符串:Node.componentId -> Component._idComponent.productId -> Product._id。
对于Component(stock) -> Product(Catalog)的关系,我尝试了一下
LookupOperation lookupOperation = LookupOperation.newLookup()
.from("catalog")
.localField("productId")
.foreignField("_id")
.as("product");
TypedAggregation<Component> agg =
Aggregation.newAggregation(
Component.class,
lookupOperation
);
AggregationResults<Component> results = mongoTemplate.aggregate(agg, "stock", Component.class);
return results.getMappedResults();
但它返回的是整个组件记录,没有产品信息。
[{"_id":"5ec78573b9eb171b72f721b0","uuId":"da8800d0-b0af-4886-80d1-c384596d2261","serialNumber":"706d93ef-abf5-4f08-9cbd-e7be0af1681c","bareCode":"90168.94737714577","productId":"5ec7856eb9eb171b72f721a9","created":"2020-05-22T07:55:31.66","updated":null}, .....]
谢谢您的帮助。
请注意。除了@Valijon的回答之外,要想得到预期的结果,返回的对象必须包含一个 "product "属性,要么什么都不返回(例如使用JSON REST服务)。
public class ComponentExpanded implements Serializable {
private String product;
....
与
AggregationResults<ComponentExpanded> results =
mongoTemplate.aggregate(agg,mongoTemplate.getCollectionName(Component.class), ComponentExpanded.class);
问题在于 productId
和_id
正如你所观察到的。
为了加入这些数据,我们需要执行 不相关的子序列 而不是每一个 "新 "功能都能立即进入抽象层,如 spring-mongo
.
试试这个。
Aggregation agg = Aggregation.newAggregation(l -> new Document("$lookup",
new Document("from", mongoTemplate.getCollectionName(Product.class))
.append("let", new Document("productId", new Document("$toObjectId", "$productId")))
.append("pipeline",
Arrays.asList(new Document("$match",
new Document("$expr",
new Document("$eq", Arrays.asList("$_id", "$$productId"))))))
.append("as", "product")),
Aggregation.unwind("product", Boolean.TRUE));
AggregationResults<Component> results = mongoTemplate.aggregate(agg,
mongoTemplate.getCollectionName(Component.class), Component.class);
return results.getMappedResults();
MongoPlayground 请看这里的shell查询是怎样的。
请注意。 对于Java v1.7
,你需要实现 AggregationOperation
像下面这样。
AggregationOperation l = new AggregationOperation() {
@Override
public Document toDocument(AggregationOperationContext context) {
return new Document(...); // put here $lookup stage
}
};