Spring Mongo聚集项目过滤器 [英] Spring Mongo Aggregation Project Filter

查看:54
本文介绍了Spring Mongo聚集项目过滤器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Mongo Shell中使用的投影上实现滤镜时遇到问题.我有一个人口普查对象,其中包含员工列表.

I'm having an issue implementing a Filter on a Projection that I have working in the Mongo Shell. I've got a Census object that contains a list of Employees.

{
   "_id": "ID",
   "name": "census1",
   "employees": [ {
      "eeId": "EE_ID1"
   }, 
   {
      "eeId": "EE_ID2"
   },
   {
      "eeId": "EE_ID3"
   }
}

实际上,这可能包含很多员工.因此,我希望能够检索主要的人口普查对象以及部分雇员.我已经实现了切片",因此这将通过其eeId检索一组员工.

Realistically this could contain a lot of employees. So I'd like to be able to retrieve the main Census object, and a subset of employees. I've already implemented 'slice', so this is going to be retrieving a set of employees by their eeId.

这很好:

db.census.aggregate( 
    [
        {
            $match: {
                "_id": ObjectId("ID1")
            }
        },
        {
            $project: {
                "censusName": 1,
                "employees" : {
                    $filter : {
                        input: "$employees",
                        as: "employees",
                        cond: { $in: [ "$$employees.eeId", ["EE_ID1", "EE_ID3"]] } 
                    }
                }
            }
        }
    ]
).toArray()

问题是,我无法用Java实现它.这里的"employeeIds"是我想要的ID的字符串.

The problem is, I can't get it implemented in Java. Here 'employeeIds' is a String of the IDs I want.

MatchOperation matchCensusIdStage = Aggregation.match(new Criteria("id").is(censusId));
ProjectionOperation projectStage = Aggregation.project("censusName")
        .and(Filter.filter("employees")
        .as("employees")
        .by(In.arrayOf(employeeIds).containsValue("employees.eeId")))
.as("employees");

Aggregation aggregation = Aggregation.newAggregation(matchCensusIdStage, projectStage);

return mongoTemplate.aggregate(aggregation, Census.class, Census.class).getMappedResults().get(0);

为此,不返回任何结果.我也尝试过使用BasicDBObject实现它,但是也被卡在那里.

For this, no results are returned. I've also tried implementing it with a BasicDBObject but got stuck there too.

编辑(解决方法):我确实获得了使用聚合的解决方案,但没有使用项目中的过滤器.这就是我所做的:

EDIT (workaround): I did get a solution using aggregation but not with the filter on the project. This is what I did:

db.parCensus.aggregate( 
// Pipeline
[
    {
        $match: {
            "_id": ObjectId("ID1")
        }
    },
    {
        $project: {
            "_id": 0, "employee": "$employees"
        }
    },
    {
        $unwind: "$employee"
    },
    {
        $match: {
            "employee.eeId": { $in: ["EE_ID1", "EE_ID3"] }
        }
    }
]
).toArray()

Java代码:

    MatchOperation matchCensusIdStage = Aggregation.match(new Criteria("id").is(censusId));
    ProjectionOperation projectStage = Aggregation.project("censusName").and("employees").as("employee");
    UnwindOperation unwindStage = Aggregation.unwind("employee");
    MatchOperation matchEmployeeIdsStage = Aggregation.match(new Criteria("employee.eeId").in(employeeIds));

    Aggregation aggregation = Aggregation.newAggregation(matchCensusIdStage, projectStage, unwindStage, matchEmployeeIdsStage);

我知道我可以在末尾添加一个$ group并将其放回一个Census对象,但是我只是创建了一个单独的CensusEmployee对象来存储所有对象.

I know I could add a $group at the end to put it back into one Census object, but I just created a separate CensusEmployee object to store it all.

推荐答案

问题帖中发布的聚合查询工作正常.用于聚合 ArrayOperators.In 语法的MongoDB Spring Data API尚不清楚.我无法基于此聚合(也没有与网络相关的答案)实现解决方案.

The aggregation query posted in the question post works fine. The MongoDB Spring Data API for the aggregation ArrayOperators.In syntax is not clear. I couldn't implement a solution based on this aggregation (and no answers related to on the net).

但是,替代解决方案基于以下聚合查询-并且效果很好.

But, the alternative solution is based on the following aggregation query - and it works fine.

db.collection.aggregate( [
  { $unwind: "$employees" },
  { $match: { "employees.eeId": { $in: ["EE_ID1", "EE_ID3"] } } },
  { $group: { _id: "$_id", name: { $first: "$name" }, employees: { $push: "$employees" } } }
] )

Java代码:

List<String> empsToMatch = Arrays.asList("EE_ID1", "EE_ID3");

MongoOperations mongoOps = new MongoTemplate(MongoClients.create(), "test");
Aggregation agg = newAggregation(
    unwind("employees"),
    match(Criteria.where("employees.eeId").in(empsToMatch )),
    group("_id")
        .first("name").as("name")
        .push("employees").as("employees")
 );

AggregationResults<Document> results = mongoOps.aggregate(agg, "collection", Document.class);

这篇关于Spring Mongo聚集项目过滤器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆