当前位置: 首页 > 知识库问答 >
问题:

MongoDB将包含数组字段的文档与与查询匹配的所有元素匹配

丌官丰羽
2023-03-14

来自< code>$elementMatch的MongoDB文档:

$elemMatch运算符将包含数组字段的文档与至少一个与所有指定查询条件匹配的元素匹配。

但是,如何将包含数组字段的文档与与查询匹配的所有元素进行匹配?

例如,我有这样的文档:

{
    "_id": ObjectId("55c99649b8b5fc5b0a2f1c83"),
    "sku": "ed-39211",
    "created_at": ISODate("2015-08-11T06:29:29.139+0000"),
    "formats": [{
        "name": "thefile",
        "_id": ObjectId("55c99649f2e2d6353348ec9c"),
        "prices": [{
            "price": 4.49,
            "currency": "GBP",
            "territory": "GB",
            "_id": ObjectId("55c99649f2e2d6353348ec9f")
        }, {
            "price": 6.99,
            "currency": "USD",
            "territory": "US",
            "_id": ObjectId("55c99649f2e2d6353348ec9e")
        }, {
            "price": 6.99,
            "currency": "CHF",
            "territory": "CH",
            "_id": ObjectId("55c99649f2e2d6353348ec9d")
        }]
    }]
}

我需要匹配所有具有所有格式、价格、价格的文档

如果我使用以下查询:

{ 'formats.prices': { $elemMatch: { price: { $gte: 5 } } } }

该文档将被匹配,因为至少有一个价格

我也试过这个,但它似乎不工作:

{ 'formats.prices': { $all: { $elemMatch: {price: { $gte: 0.98 } } } } }

有没有办法排除查看所有价格而不是至少一个价格的文档?

共有2个答案

王高邈
2023-03-14

您可以使用聚合或映射减少来实现它:

第一个解决方案是使用Map Reduce:

我创建了一个名为“format”的集合,并插入了以下数据:

{
        "_id" : ObjectId("55c99649b8b5fc5b0a2f1c83"),
        "sku" : "ed-39211",
        "created_at" : ISODate("2015-08-11T06:29:29.139Z"),
        "formats" : [
                {
                        "name" : "thefile",
                        "_id" : ObjectId("55c99649f2e2d6353348ec9c"),
                        "prices" : [
                                {
                                        "price" : 4.49,
                                        "currency" : "GBP",
                                        "territory" : "GB",
                                        "_id" : ObjectId("55c99649f2e2d6353348ec9f")
                                },
                                {
                                        "price" : 6.99,
                                        "currency" : "USD",
                                        "territory" : "US",
                                        "_id" : ObjectId("55c99649f2e2d6353348ec9e")
                                },
                                {
                                        "price" : 6.99,
                                        "currency" : "CHF",
                                        "territory" : "CH",
                                        "_id" : ObjectId("55c99649f2e2d6353348ec9d")
                                }
                        ]
                }
        ]
}
{
        "_id" : ObjectId("55c99649b8b5fc5b0a2f1c84"),
        "sku" : "ed-39211",
        "created_at" : ISODate("2015-08-11T06:29:29.139Z"),
        "formats" : [
                {
                        "name" : "thefile",
                        "_id" : ObjectId("55c99649f2e2d6353348ec9a"),
                        "prices" : [
                                {
                                        "price" : 5.49,
                                        "currency" : "GBP",
                                        "territory" : "GB",
                                        "_id" : ObjectId("55c99649f2e2d6353348ec9f")
                                },
                                {
                                        "price" : 6.99,
                                        "currency" : "USD",
                                        "territory" : "US",
                                        "_id" : ObjectId("55c99649f2e2d6353348ec9e")
                                },
                                {
                                        "price" : 6.99,
                                        "currency" : "CHF",
                                        "territory" : "CH",
                                        "_id" : ObjectId("55c99649f2e2d6353348ec9d")
                                }
                        ]
                }
        ]
}

Map_reduce:

db.format.mapReduce(
    function()
            {
            var doc  = {"_id" : this._id, "sku" : this.sku, "created_at" : this.created_at, "formats" : this.formats};
            var prices;
            var flag = 0;
            for ( var i = 0 ; i < doc.formats.length; i++)
            {
                prices = doc.formats[i].prices
                for ( var j =0 ; j < prices.length; j++)
                {
                    if( prices[j].price < 5)
                    {
                        flag = 1;
                        break;
                    }
                }
                if( flag == 1)
                doc.formats.splice(i,1);
            }
                if( doc.formats.length > 0 )
                emit( this._id, doc);
            },
    function(){},
    { "out": { "inline": 1 } }
)

输出:

{
        "results" : [
                {
                        "_id" : ObjectId("55c99649b8b5fc5b0a2f1c84"),
                        "value" : {
                                "_id" : ObjectId("55c99649b8b5fc5b0a2f1c84"),
                                "sku" : "ed-39211",
                                "created_at" : ISODate("2015-08-11T06:29:29.139Z"),
                                "formats" : [
                                        {
                                                "name" : "thefile",
                                                "_id" : ObjectId("55c99649f2e2d6353348ec9a"),
                                                "prices" : [
                                                        {
                                                                "price" : 5.49,
                                                                "currency" : "GBP",
                                                                "territory" : "GB",
                                                                "_id" : ObjectId("55c99649f2e2d6353348ec9f")
                                                        },
                                                        {
                                                                "price" : 6.99,
                                                                "currency" : "USD",
                                                                "territory" : "US",
                                                                "_id" : ObjectId("55c99649f2e2d6353348ec9e")
                                                        },
                                                        {
                                                                "price" : 6.99,
                                                                "currency" : "CHF",
                                                                "territory" : "CH",
                                                                "_id" : ObjectId("55c99649f2e2d6353348ec9d")
                                                        }
                                                ]
                                        }
                                ]
                        }

第二个使用聚合的解决方案:

使用聚合运算符$unwod和$size,我们可以使用以下查询获得所需的结果:

在$unwind“格式”和“格式.价格”之后,取“格式.价格”的大小,然后对“价格”进行$match,并再次计算“格式.价格”的新大小。

如果大小相同,则“格式”字段中的所有“价格”都大于5,文档将被投影。

db.format.aggregate([
{ $unwind: "$formats" },
{ $project : { _id : 1, sku : 1, created_at : 1, formats : 1, "size" : { $size : "$formats.prices" } } },
{ $unwind: "$formats.prices" },
{ $match: { "formats.prices.price" : { $gt:5 } } },
{ $group: { _id: { "name" : "$formats.name" , "_id" : "$formats._id", "id" : "$_id" }, prices : { $push: "$formats.prices" } , sku: { $first: "$sku" }, created_at : { $first: "$created_at" }, oldsize : { $first: "$size" } } },
{ $project: { _id : 1, prices : 1, sku : 1, created_at : 1, oldsize : 1, newsize : {$size: "$prices" } } },
{ $project: { _id : 1, prices : 1, sku : 1, created_at : 1, cmp_value: { $cmp: ["$oldsize", "$newsize"] } } },
{ $match: { cmp_value:{ $eq:0 } } },
{ $group : { _id : "$_id.id" , sku: { $first: "$sku" }, created_at : { $first: "$created_at" }, formats : { $push: { name : "$_id.name", "_id" : "$_id._id", prices: "$prices" } }  } }
                  ]).pretty() 

输出:

{
        "_id" : ObjectId("55c99649b8b5fc5b0a2f1c84"),
        "sku" : "ed-39211",
        "created_at" : ISODate("2015-08-11T06:29:29.139Z"),
        "formats" : [
                {
                        "name" : "thefile",
                        "_id" : ObjectId("55c99649f2e2d6353348ec9a"),
                        "prices" : [
                                {
                                        "price" : 5.49,
                                        "currency" : "GBP",
                                        "territory" : "GB",
                                        "_id" : ObjectId("55c99649f2e2d6353348ec9f")
                                },
                                {
                                        "price" : 6.99,
                                        "currency" : "USD",
                                        "territory" : "US",
                                        "_id" : ObjectId("55c99649f2e2d6353348ec9e")
                                },
                                {
                                        "price" : 6.99,
                                        "currency" : "CHF",
                                        "territory" : "CH",
                                        "_id" : ObjectId("55c99649f2e2d6353348ec9d")
                                }
                        ]
                }
        ]
}
赵永逸
2023-03-14

找到了!这很容易,只需使用$not运算符并检查相反的(

{ 'formats.prices': { $not: { $elemMatch: {price: { $lt: 5 } } } } }
 类似资料:
  • 问题内容: 我有一个与此类似的文件: 我要查询以查找所有包含“ a”的人(鲍勃和玛丽)。如何编写查询? 编辑: 当前查询: 问题答案: 在字段上使用术语过滤器/查询(例如)可以满足您的需求。假设您只想匹配满足该条件的任何文档,则完整查询将类似于: 之所以可行,是因为值数组是分别索引的,并且如果查询的字段是列表,则术语查询将查找包含包含该值的数组的文档。

  • 我有一个字符串列表,上面有一周中几天的日期。 我的目标是能够找到属于某个星期的几个文档。比较字段为“第一天”。 遵循数据库中文档结构的图像: 但是搜索没有找到任何文件。预计查询数量将为35。 我想知道是否有任何方法可以通过给定的文档字段找到文档,匹配arraylist中的任何项。

  • 问题内容: 我有一个MongoDB,用于存储来自不同传感器的数据。它具有以下结构: 现在,例如,我需要“心率”-包含所有字段和“数据”字段的文档-匹配条件“ 1483537204000和1483537214000之间的时间戳记”的子文档。 我已经在另一个问题中的mongo shell中获得了有关如何执行此操作的答案。参见以下代码: 但是如何在java spring-data中做到这一点?似乎在sp

  • 以下是更详细的错误消息: 我将代码中的问题隔离在下面的某个地方,尽管我不知道抛出这个异常的具体原因: gradle.build-项目

  • 我有一个集合,其中包含具有以下结构的文档: 我想在1个查询中获取存在或等于的所有文档。即与列表中的键匹配的文档。 在MongoDB中有没有办法做到这一点?

  • 问题内容: 我想获取与“ statusCode”不匹配的结果:200 为了匹配字段中的文本,您可以使用 我尝试过这样的事情: 根据:https : //www.elastic.co/guide/zh- CN/elasticsearch/reference/current/query-dsl-bool- query.html 问题答案: 试试这个