如何使用morphia

时间:2016-07-05 06:52:29

标签: arrays mongodb morphia

鉴于我的个人资料数据如下所示,我想找到userName和productId组合的个人资料  并且只返回与该产品的相应合同的配置文件。

{
    "firstName": "John",
    "lastName": "Doe",
    "userName": "john.doe@gmail.com",
    "language": "NL",
    "timeZone": "Europe/Amsterdam",
    "contracts": [
        {
            "contractId": "DEMO1-CONTRACT",
            "productId": "ticket-api",
            "startDate": ISODate('2016-06-29T09:06:42.391Z'),
            "roles": [
                {
                    "name": "Manager",
                    "permissions": [
                        {
                            "activity": "ticket",
                            "permission": "createTicket"
                        },
                        {
                            "activity": "ticket",
                            "permission": "updateTicket"
                        },
                        {
                            "activity": "ticket",
                            "permission": "closeTicket"
                        }
                    ]
                }
            ]
        },
        {
            "contractId": "DEMO2-CONTRACT",
            "productId": "comment-api",
            "startDate": ISODate('2016-06-29T10:27:45.899Z'),
            "roles": [
                {
                    "name": "Manager",
                    "permissions": [
                        {
                            "activity": "comment",
                            "permission": "createComment"
                        },
                        {
                            "activity": "comment",
                            "permission": "updateComment"
                        },
                        {
                            "activity": "comment",
                            "permission": "deleteComment"
                        }
                    ]
                }
            ]
        }
    ]
}    

我设法从命令行找到解决方法。但我似乎没有办法用Morphia(最新版本)来实现这一目标。

db.Profile.aggregate([
    { $match: {"userName": "john.doe@gmail.com"}},
    { $project: {
        contracts: {$filter: {
            input: '$contracts',
            as: 'contract',
            cond: {$eq: ['$$contract.productId', "ticket-api"]}
        }}
    }}
])

这是我到目前为止所拥有的。非常感谢任何帮助

Query<Profile> matchQuery = getDatastore().createQuery(Profile.class).field(Profile._userName).equal(userName);
getDatastore()
     .createAggregation(Profile.class)
     .match(matchQuery)
     .project(Projection.expression(??))

注意......同时我找到了另一种不使用聚合管道的解决方案。

    public Optional<Profile> findByUserNameAndContractQuery(String userName, String productId) {
        DBObject contractQuery = BasicDBObjectBuilder.start(Contract._productId, productId).get();
        Query<Profile> query =
                getDatastore()
                        .createQuery(Profile.class)
                        .field(Profile._userName).equal(userName)
                        .filter(Profile._contracts + " elem", contractQuery)
                        .retrievedFields(true, Profile._contracts + ".$");
        return Optional.ofNullable(query.get());
    } 

2 个答案:

答案 0 :(得分:0)

我终于找到了最好的方法(假设我只想从数组返回最多1个元素)来过滤嵌入式数组。

db.Profile.aggregate([
   { $match: {"userName": "john.doe@gmail.com"}},
   { $unwind: "$contracts"},
   { $match: {"contracts.productId": "comment-api"}}
])

答案 1 :(得分:0)

要根据您的第一个设计进行匹配,您可以尝试使用morphia聚合管道进行投影设置。

Query<Profile> matchQuery = getDatastore().createQuery(Profile.class).field(Profile._userName).equal(userName);

getDatastore()
 .createAggregation(Profile.class)
 .match(matchQuery)
 .project(Projection.expression("$filter", new BasicDBObject()
      .append("input", "$contracts")
      .append("as", "contract")
      .append("cond", new BasicDBObject()
          .append("$eq", Arrays.asList('$$contract.productId', "ticket-api")));

另请参阅morphia工作人员在https://github.com/mongodb/morphia/blob/master/morphia/src/test/java/org/mongodb/morphia/aggregation/AggregationTest.java附近第88行写的示例。