如何找到在MongoDB中收集的文件和子文件单独匹配给出规定 - [英] How to find document and single subdocument matching given criterias in MongoDB collection

查看:126
本文介绍了如何找到在MongoDB中收集的文件和子文件单独匹配给出规定 - 的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的产品集合。每个产品包含的项目数组。

 > db.products.find()。pretty()
{
    _id:的ObjectId(54023e8bcef998273f36041d),
    店:shop1
    名:产品1,
    项目:
            {
                    日期:2100年2月1日
                    进价:1,
                    sellingPrice:10,
                    伯爵:15
            },
            {
                    日期:2014年8月31日
                    进价:10,
                    sellingPrice:1,
                    伯爵:5
            }
    ]
}

那么,能不能请你给我一个建议,我怎么能MongoDB的查询检索所有的产品与日期只有一个项目等于我通过查询作为参数的日期。

有关2014年8月31日的结果必然是:

  {
    _id:的ObjectId(54023e8bcef998273f36041d),
    店:shop1
    名:产品1,
    项目:
            {
                    日期:2014年8月31日
                    进价:10,
                    sellingPrice:1,
                    伯爵:5
            }
    ]
}


解决方案

你所寻找的是位置 $ 运营商和投影。对于单场则需要使用点号所要求的数组元素来搭配,为多个领域使用<一个href=\"http://docs.mongodb.org/manual/reference/operator/query/elemMatch/\"><$c$c>$elemMatch:

db.products.find(
    {items.date:2014年8月31日},
    {店:1,名:1,项目$:1}

$ elemMatch 的一个以上的匹配字段:

db.products.find(
    {项目:{
        $ elemMatch:{日期:2014年8月31日,进价:1}
    }},
    {店:1,名:1,项目$:1}

这些工作,为单个数组元素虽然只,只有一个将被退回。如果你想从你的条件,然后返回多个数组元素你需要更先进的聚合框架处理。

db.products.aggregate([
    {$匹配:{items.date:2014年8月31日}},
    {$开卷:$项目},
    {$匹配:{items.date:2014年8月31日}},
    {$组:{
        _id:$ _id
        店:{$第一:$店},
        名:{$第一:$名},
        项目:{$推:$项目}
    }}
])

或者可能在较短/更快的形式,因为2.6的MongoDB,当商品的数组中包含的唯一条目:

db.products.aggregate([
    {$匹配:{items.date:2014年8月31日}},
    {$工程:{
        店:1,
        名:1,
        项目:{
            $ setDifference:[
                {$图:{
                    输入:$项目
                    作为:厄尔尼诺
                    在:{
                        $ COND:[
                            {$情商:$$ e​​l.date,2014年8月31日]},
                            $$报
                            假
                        ]
                    }
                }},
                [假]
            ]
        }
    }}
])

或可能<一个href=\"http://docs.mongodb.org/manual/reference/operator/aggregation/redact/\"><$c$c>$redact,但有点做作:

db.products.aggregate([
    {$匹配:{items.date:2014年8月31日}},
    {$纂:{
        $ COND:[
             {$情商:[{$ IFNULL:[$日,2014年8月31日]},2014年8月31日]},
             $$下潜
             $$剪枝
         ]
    }}
])

所以它只是取决于你是否总是期待一个单一的元素,以配合或多个元素,然后哪种方法更好。但是,在可能的 .find()方法一般会更快,因为它缺乏其他操作的开销,这在那些最后的形式不落后,远远落后于所有

作为一个方面说明,你的日期是psented字符串重新$ P $这是不是一个很好的主意前进。考虑更改这些适当日期 对象类型,这将大大帮助你在未来。

I have collection of products. Each product contains array of items.

> db.products.find().pretty()
{
    "_id" : ObjectId("54023e8bcef998273f36041d"),
    "shop" : "shop1",
    "name" : "product1",
    "items" : [
            {
                    "date" : "01.02.2100",
                    "purchasePrice" : 1,
                    "sellingPrice" : 10,
                    "count" : 15
            },
            {
                    "date" : "31.08.2014",
                    "purchasePrice" : 10,
                    "sellingPrice" : 1,
                    "count" : 5
            }
    ]
}

So, can you please give me an advice, how I can query MongoDB to retrieve all products with only single item which date is equals to the date I pass to query as parameter.

The result for "31.08.2014" must be:

    {
    "_id" : ObjectId("54023e8bcef998273f36041d"),
    "shop" : "shop1",
    "name" : "product1",
    "items" : [
            {
                    "date" : "31.08.2014",
                    "purchasePrice" : 10,
                    "sellingPrice" : 1,
                    "count" : 5
            }
    ]
}

解决方案

What you are looking for is the positional $ operator and "projection". For a single field you need to match the required array element using "dot notation", for more than one field use $elemMatch:

db.products.find(
    { "items.date": "31.08.2014" },
    { "shop": 1, "name":1, "items.$": 1 }
)

Or the $elemMatch for more than one matching field:

db.products.find(
    { "items":  { 
        "$elemMatch": { "date": "31.08.2014",  "purchasePrice": 1 }
    }},
    { "shop": 1, "name":1, "items.$": 1 }
)

These work for a single array element only though and only one will be returned. If you want more than one array element to be returned from your conditions then you need more advanced handling with the aggregation framework.

db.products.aggregate([
    { "$match": { "items.date": "31.08.2014" } },
    { "$unwind": "$items" },
    { "$match": { "items.date": "31.08.2014" } },
    { "$group": {
        "_id": "$_id",
        "shop": { "$first": "$shop" },
        "name": { "$first": "$name" },
        "items": { "$push": "$items" }
    }}
])

Or possibly in shorter/faster form since MongoDB 2.6 where your array of items contains unique entries:

db.products.aggregate([
    { "$match": { "items.date": "31.08.2014" } },
    { "$project": {
        "shop": 1,
        "name": 1,
        "items": {
            "$setDifference": [
                { "$map": {
                    "input": "$items",
                    "as": "el",
                    "in": {
                        "$cond": [
                            { "$eq": [ "$$el.date", "31.08.2014" ] },
                            "$$el",
                            false 
                        ]
                    }
                }},
                [false]
            ]
        }
    }}
])

Or possibly with $redact, but a little contrived:

db.products.aggregate([
    { "$match": { "items.date": "31.08.2014" } },
    { "$redact": {
        "$cond": [
             { "$eq": [ { "$ifNull": [ "$date", "31.08.2014" ] }, "31.08.2014" ] },
             "$$DESCEND",
             "$$PRUNE"
         ]
    }}
])

So it just depends on whether you always expect a single element to match or multiple elements, and then which approach is better. But where possible the .find() method will generally be faster since it lacks the overhead of the other operations, which in those last to forms does not lag that far behind at all.

As a side note, your "dates" are represented as strings which is not a very good idea going forward. Consider changing these to proper Date object types, which will greatly help you in the future.

这篇关于如何找到在MongoDB中收集的文件和子文件单独匹配给出规定 - 的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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