Spring data MongoDb 聚合查找从 String 到 ObjectId



我正在使用 Spring (boot( 数据 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;
....

productId字段是指目录集合中_id

字段操作

{
"_id" : ObjectId("5ec78671b9eb171b72f721d3"),
"componentId" : ""5ec78573b9eb171b72f721ba",
.....
}

映射者

public class Node implements Serializable {
@Id
private String _id;
private String componentId;
....

组件 ID字段是指库存集合中_id

字段我想查询操作库存集合,以检索按 Product.model 字段(在目录集合中(排序的相应节点或组件对象列表。

虽然目标是用 Java 编码,但我试图首先在Mongo shell中发出请求,但我什至无法让它工作,因为我试图用 ObjectId 连接(查找(一个字符串:Node.componentId -> Component._id Component.productId -> Product._id

对于我尝试过的组件(库存(->产品(目录(的关系

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 查询的样子。

注意:对于 Javav1.7,您需要实现如下AggregationOperation

AggregationOperation l = new AggregationOperation() {
@Override
public Document toDocument(AggregationOperationContext context) {
return new Document(...); // put here $lookup stage
}
};

最新更新