如何在两个关键范围之间查询MongoDB

时间:2015-08-03 14:49:45

标签: arrays mongodb

我有一个名为member_transaction的集合。示例文档结构如下:

{
    "memberId": "XY-123",
    "transactionsDetails": {
        "2015-07-15": [
            {
                "memberId": "1011",
                "orderId": "232",
                "topLevelcategory": "household",
                "orderValue": "34313.200"
            },
            {
                "memberId": "1011",
                "orderId": "235",
                "topLevelcategory": "Furniture",
                "orderValue": "2534.200"
            }
        ],
        "2015-07-16": [
            {
                "memberId": "1011",
                "orderId": "235",
                "topLevelcategory": "Furniture",
                "orderValue": "2534.200"
            },
            {
                "memberId": "1012",
                "orderId": "235",
                "topLevelcategory": "Grocery",
                "orderValue": "2534.200"
            },
            {
                "memberId": "1013",
                "orderId": "235",
                "topLevelcategory": "Grocery",
                "orderValue": "2534.200"
            },
            {
                "memberId": "1014",
                "orderId": "235",
                "topLevelcategory": "Grocery",
                "orderValue": "2534.200"
            }
        ],
        "2015-07-18": [
            {
                "memberId": "2011",
                "orderId": "1232",
                "topLevelcategory": "household",
                "orderValue": "34313.200"
            },
            {
                "memberId": "103",
                "orderId": "2352",
                "topLevelcategory": "Furniture",
                "orderValue": "2534.200"
            }
        ],
        "2015-07-19": [
            {
                "memberId": "311",
                "orderId": "152",
                "topLevelcategory": "household",
                "orderValue": "34313.200"
            },
            {
                "memberId": "1013",
                "orderId": "2312",
                "topLevelcategory": "Furniture",
                "orderValue": "2534.200"
            },
            {
                "memberId": "1043",
                "orderId": "2316",
                "topLevelcategory": "Grocery",
                "orderValue": "2534.200"
            },
            {
                "memberId": "1017",
                "orderId": "2315",
                "topLevelcategory": "Furniture",
                "orderValue": "2544"
            }
        ]
    }
}

如何查询在两个密钥之间具有数组结构的mongoDB,即如何在密钥"2015-07-16"&之间提取数据。上述文件中的"2015-07-19"

1 个答案:

答案 0 :(得分:1)

查询具有动态密钥的此类架构将非常困难。更好的推荐方法是重新设计模式,使得嵌入式文档具有保存日期值的date键和存储数组的transactionDetails键。以下演示了理想的架构更改:

db.member_transaction.insert({
    "memberId": "XY-123",
    "transactions": [
        {
            "date": ISODate("2015-07-15"),
            "transactionsDetails": [
                {
                    "memberId": "1011",
                    "orderId": "232",
                    "topLevelcategory": "household",
                    "orderValue": "34313.200"
                },
                {
                    "memberId": "1011",
                    "orderId": "235",
                    "topLevelcategory": "Furniture",
                    "orderValue": "2534.200"
                }
            ]
        },
        {
            "date": ISODate("2015-07-16"),
            "transactionsDetails": [
                {
                    "memberId": "1011",
                    "orderId": "235",
                    "topLevelcategory": "Furniture",
                    "orderValue": "2534.200"
                },
                {
                    "memberId": "1012",
                    "orderId": "235",
                    "topLevelcategory": "Grocery",
                    "orderValue": "2534.200"
                },
                {
                    "memberId": "1013",
                    "orderId": "235",
                    "topLevelcategory": "Grocery",
                    "orderValue": "2534.200"
                },
                {
                    "memberId": "1014",
                    "orderId": "235",
                    "topLevelcategory": "Grocery",
                    "orderValue": "2534.200"
                }
            ]
        },
        {
            "date": ISODate("2015-07-18"),
            "transactionsDetails": [
                {
                    "memberId": "2011",
                    "orderId": "1232",
                    "topLevelcategory": "household",
                    "orderValue": "34313.200"
                },
                {
                    "memberId": "103",
                    "orderId": "2352",
                    "topLevelcategory": "Furniture",
                    "orderValue": "2534.200"
                }
            ]
        },
        {
            "date": ISODate("2015-07-19"),
            "transactionsDetails": [
                {
                    "memberId": "311",
                    "orderId": "152",
                    "topLevelcategory": "household",
                    "orderValue": "34313.200"
                },
                {
                    "memberId": "1013",
                    "orderId": "2312",
                    "topLevelcategory": "Furniture",
                    "orderValue": "2534.200"
                },
                {
                    "memberId": "1043",
                    "orderId": "2316",
                    "topLevelcategory": "Grocery",
                    "orderValue": "2534.200"
                },
                {
                    "memberId": "1017",
                    "orderId": "2315",
                    "topLevelcategory": "Furniture",
                    "orderValue": "2544"
                }
            ]
        }
    ]
})

使用上面的架构,您可以使用 aggregation framework 查询具有该日期范围的文档。以下聚合管道将实现所需的结果:

db.member_transaction.aggregate([
    {
        "$match": {
            "transactions.date": {
                "$gte": ISODate("2015-07-16T00:00:00.000Z"),
                "$lte": ISODate("2015-07-19T00:00:00.000Z")
            }
        }
    },
    {
        "$unwind": "$transactions"
    },
    {
        "$match": {
            "transactions.date": {
                "$gte": ISODate("2015-07-16T00:00:00.000Z"),
                "$lte": ISODate("2015-07-19T00:00:00.000Z")
            }
        }
    },
    {
        "$group": {
            "_id": null,
            "memberId": { "$first": "$memberId" },
            "transactions": { "$push": "$transactions" }
        }
    }
])

示例输出

/* 0 */
{
    "result" : [ 
        {
            "_id" : null,
            "memberId" : "XY-123",
            "transactions" : [
                {
                    "date" : ISODate("2015-07-16T00:00:00.000Z"),
                    "transactionsDetails" : [ 
                        {
                            "memberId" : "1011",
                            "orderId" : "235",
                            "topLevelcategory" : "Furniture",
                            "orderValue" : "2534.200"
                        }, 
                        {
                            "memberId" : "1012",
                            "orderId" : "235",
                            "topLevelcategory" : "Grocery",
                            "orderValue" : "2534.200"
                        }, 
                        {
                            "memberId" : "1013",
                            "orderId" : "235",
                            "topLevelcategory" : "Grocery",
                            "orderValue" : "2534.200"
                        }, 
                        {
                            "memberId" : "1014",
                            "orderId" : "235",
                            "topLevelcategory" : "Grocery",
                            "orderValue" : "2534.200"
                        }
                    ]
                }, 
                {
                    "date" : ISODate("2015-07-18T00:00:00.000Z"),
                    "transactionsDetails" : [ 
                        {
                            "memberId" : "2011",
                            "orderId" : "1232",
                            "topLevelcategory" : "household",
                            "orderValue" : "34313.200"
                        }, 
                        {
                            "memberId" : "103",
                            "orderId" : "2352",
                            "topLevelcategory" : "Furniture",
                            "orderValue" : "2534.200"
                        }
                    ]
                }, 
                {
                    "date" : ISODate("2015-07-19T00:00:00.000Z"),
                    "transactionsDetails" : [ 
                        {
                            "memberId" : "311",
                            "orderId" : "152",
                            "topLevelcategory" : "household",
                            "orderValue" : "34313.200"
                        }, 
                        {
                            "memberId" : "1013",
                            "orderId" : "2312",
                            "topLevelcategory" : "Furniture",
                            "orderValue" : "2534.200"
                        }, 
                        {
                            "memberId" : "1043",
                            "orderId" : "2316",
                            "topLevelcategory" : "Grocery",
                            "orderValue" : "2534.200"
                        }, 
                        {
                            "memberId" : "1017",
                            "orderId" : "2315",
                            "topLevelcategory" : "Furniture",
                            "orderValue" : "2544"
                        }
                    ]
                }
            ]
        }
    ],
    "ok" : 1
}

<强>更新

您可以使用 $elemMatch 投影运算符来限制查询结果中字段的内容,但不能仅使用第一个元素匹配 $elemMatch 条件(即具有日期transactionDetails的{​​{1}}数组文档),因此聚合框架是首选方法,因为它返回所有期望的结果。 / p>

以下内容还演示了 $elemMatch 运算符在您的示例中的工作原理:

"2015-07-16"

示例输出

db.member_transaction.find(
    {
        "transactions.date": {
            "$gte": ISODate("2015-07-16T00:00:00.000Z"),
            "$lte": ISODate("2015-07-19T00:00:00.000Z")
        }
    }, 
    {
        "memberId": 1,
        "transactions": {
            "$elemMatch": {
                "date": {
                    "$gte": ISODate("2015-07-16T00:00:00.000Z"),
                    "$lte": ISODate("2015-07-19T00:00:00.000Z")
                }
            }
        }
    }
)