如何在python中为包含嵌套文档列表的文档创建mongoDB聚合查询?

时间:2018-04-11 11:20:23

标签: python mongodb mongodb-query aggregation-framework

我有一个mongoDB集合,其文档看起来像:

@Entity
@Getter
@Setter
@AllArgsConstructor
public class Foo{
    @ManyToOne
    @JoinColumn(name = "BAR_ID")
    private Bar bar'
}



@Component
public class FooAssembler{
       @Autowired
       private BarRepository barRepository;

       public Foo toFoo(Long barId){
          return new Foo(barRepository.getOne(barId))
       }
}

我想从{ "_id" : "132743", "RECORD_DATA" : [ { "FIELD_TYPE" : "Primary", "DATA" : "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec blandit leo sit amet nisi ultricies bibendum. Aenean efficitur pharetra diam, non pretium nisi blandit eu. Maecenas eget dolor sed ipsum semper posuere id eget purus. Ut tempor massa vel porta euismod. Vivamus et elementum justo. Aliquam porta, ipsum at semper pulvinar, turpis ipsum congue orci, a fringilla turpis arcu eget lorem. Vestibulum consectetur sapien neque, at vulputate mi congue vitae.", "DETAIL" : "XYZ" }, { "FIELD_TYPE" : "Secondary", "DATA" : "Nullam congue aliquam risus. Aenean semper ut elit id viverra. Mauris tincidunt non justo et tempor. Donec non tempus sapien. Curabitur facilisis risus tortor, nec bibendum libero feugiat sed. Curabitur eu quam ac mi sodales ultricies. Cras posuere tincidunt faucibus.", "DETAIL" : "XYZ" }, { "FIELD_TYPE" : "Secondary", "DATA" : "Lorem ipsum dolor sit amet, consectetur adipiscing elit. ", "DETAIL" : "ABC" }, { "FIELD_TYPE" : "Secondary", "DATA" : "Maecenas volutpat facilisis tortor sed pellentesque. Quisque tristique sem sit amet ipsum convallis porttitor. Vestibulum a tempus ex. Donec molestie tortor est, sed malesuada sapien maximus vel.", "DETAIL" : "ABC" }, { "FIELD_TYPE" : "optional1", "DATA" : "Curabitur faucibus dolor nisl, at venenatis tortor fermentum at. Vestibulum sodales posuere neque id aliquet. Aliquam dignissim ex quis lacus fermentum, at consectetur nunc viverra. ", "DETAIL" : "XYZ" }, { "FIELD_TYPE" : "optional2", "DATA" : "Cras vulputate lacinia elit, eu fringilla neque imperdiet eget. Nam placerat venenatis felis at pharetra. Praesent vestibulum ligula sit amet elit dignissim suscipit. ", "DETAIL" : "QWE" } ] } 中提取单个字段,其中RECORD_DATA设置为FIELD_TYPE以及Primary,用于集合中的每个文档。我的最终输出应该如下:

_id

我尝试了聚合查询:

{
    "_id" : "132743",
    "DATA" : "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec blandit leo sit amet nisi ultricies bibendum. Aenean efficitur pharetra diam, non pretium nisi blandit eu. Maecenas eget dolor sed ipsum semper posuere id eget purus. Ut tempor massa vel porta euismod. Vivamus et elementum justo. Aliquam porta, ipsum at semper pulvinar, turpis ipsum congue orci, a fringilla turpis arcu eget lorem. Vestibulum consectetur sapien neque, at vulputate mi congue vitae."
}

这不给我任何输出。任何人都可以帮我创建一个查询吗?

3 个答案:

答案 0 :(得分:2)

尝试此查询:

db.collection.aggregate([{
    "$unwind": "$RECORD_DATA"
}, {
    "$match": {
        "RECORD_DATA.FIELD_TYPE": "Primary"
    }
}, {
    "$project": {
        "_id": 1,
        "DATA": "$RECORD_DATA.DATA"
    }
}])

您可以在线尝试:mongoplayground.net/p/1HY-GSMnzoX

答案 1 :(得分:1)

您可以结合使用 $arrayElemAt $map $filter 数组运算符达到预期的效果。

使用 $filter 运算符的表达式会将RECORD_DATA数组过滤为仅包含FIELD_TYPE"Primary"的文档。

$map 运算符将映射从上面返回的结果,只输出单个DATA值的数组。然后, $arrayElemAt 将返回该列表中的第一个元素,然后进行投影。

以下说明了上述内容:

MongoDatabase.db[collection].aggregate([
    { "$match": { "RECORD_DATA.FIELD_TYPE": "Primary" } },
    { "$project": {
        "DATA": {
            "$arrayElemAt": [
                {
                    "$map": {
                        "input": {
                            "$filter": {
                                "input": "$RECORD_DATA",
                                "as": "record",
                                "cond": { "$eq": ["$$record.FIELD_TYPE", "Primary"] }
                            }
                        },
                        "as": "el",
                        "in": "$$el.DATA"
                    }
                },
                0
            ]
        }
    } }
])

答案 2 :(得分:1)

db.collection.aggregate(

    // Pipeline
    [
        // Stage 1
        {
            $match: {
                RECORD_DATA: {
                    $elemMatch: {
                        FIELD_TYPE: "Primary"
                    }
                }
            }
        },

        // Stage 2
        {
            $project: {
                'RECORD_DATA': {
                    $arrayElemAt: [{
                        $filter: {
                            input: '$RECORD_DATA',
                            as: "data",
                            cond: {
                                $eq: ["$$data.FIELD_TYPE", 'Primary']
                            }
                        }
                    }, 0]
                }

            }
        },

        // Stage 3
        {
            $project: {
                _id: 1,
                DATA: '$RECORD_DATA.DATA'
            }
        }

    ]


);