RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 572289
Accepted
Vyacheslav Danshin
Vyacheslav Danshin
Asked:2020-09-30 23:52:06 +0000 UTC2020-09-30 23:52:06 +0000 UTC 2020-09-30 23:52:06 +0000 UTC

从作为文档字段的对象数组中获取对象

  • 772

有一个coll包含多个文档的集合,具有以下方案:

{
    "_id" : ObjectId(someId),
    sourceId: someId,
    "objArr" : [
        {
            "fieldA" : someValue,
            "fieldB" : someValue
        },
        {
            "fieldA" : someValue,
            "fieldB" : someValue
        },
        ...etc
    ]
}

有必要按如下方式进行选择:知道,从数组sourceId中获取字段的值fieldA和那个对象,其中两个字段都满足条件,例如,通过使用索引的标准方法,即 不使用例如。fieldBobjArr(fieldA <= С и fieldB >= С)$where

另外:在现实生活中,这可能看起来像是一项任务,即确定一组给定时期中的某个实体是否具有包含我们需要的日期的时期。

补充:当然,在后端解决这个问题并不难,因为sourceId我们可以很容易地得到整个文档,我们总是可以遍历数组并得到一个特定的对象,但我想知道mongoDB是否可以立即返回什么你需要。

或者它在概念上是错误的,或者它真的需要在后端完成,或者以平面形式存储数据,其中没有对象数组作为文档字段,并且每个这样的对象将是文档中的 2 个字段,对于一是sourceId集合中的文档数量与对象数量一样多。

mongodb
  • 3 3 个回答
  • 10 Views

3 个回答

  • Voted
  1. Best Answer
    styvane
    2020-10-02T02:32:11Z2020-10-02T02:32:11Z

    如果数组只包含一个匹配的文档,那么最佳性能选项是一个简单的find()查询。但要使其起作用,您需要使用运算符$elemMatch进行过滤。

    当然,运算符$限制了从数组中的选择,只返回与查询匹配的第一个元素。

    db.coll.find(
        { 
            "sourceId": sourceId, 
            "objArr": { 
                "$elemMatch": { 
                    "fieldA": { "$lte": 3 }, 
                    "fieldB": { "$gte": 5 } 
                } 
            }
        },
        { "$objArr.$": 1 }
    )
    

    如果数组中有许多匹配查询的匹配文档,为了从数组中选择所有元素,您需要使用aggregate(). 这里有两个选项,具体取决于 MongoDB 版本。让我们先看看最好的选择。

    MongoDB 3.2+

    db.coll.aggregate([
        { "$match": { "sourceId": sourceId } },
        { "$project": { 
            "objArr": { 
                "$filter": { 
                    "input": "$objArr", 
                    "in": "ob", 
                    "cond": { 
                        "$and": [ 
                            { "$lte": [ "$$obj.fieldA", 3 ] },
                            { "$gte": [ "$$obj.fieldB", 5 ] },
                        ]
                    }
                }
            }
        }}
    ])
    

    MongoDB 2.6+

    db.collect.aggregate([
        { "$match": { "sourceId": sourceId } },
        { "$project": { 
            "objArr": { 
                "$setDifference": [ 
                    { "$map": { 
                        "input": "$objArr",
                        "as": "obj",
                        "in": { 
                            "$cond":  [
                                { "$and": [ 
                                    { "$lte": [ "$$obj.fieldA", 3 ] },
                                    { "$gte": [ "$$obj.fieldB", 5 ] },
                                },
                                "$$obj",
                                false
                            ]
                        }
                    },
                    [ false ]
                ]
            }
        }}
    ])
    

    解释:

    • 第一个aggregate()请求非常简单。要过滤文档,您必须使用运算符$filter。

    • 第二个选项需要更多解释:这里我们使用一个运算符$map,使用运算符,$cond您可以对数组中的每个元素进行逻辑处理,并在条件计算结果为真时返回元素,否则返回元素false。执行后生成的数组$map包含几个相等false的元素,要删除它们,请使用运算符$setDifference。

    • 3
  2. Nikolay
    2020-10-01T16:39:28Z2020-10-01T16:39:28Z

    如果允许聚合,则可以执行以下代码:

    db.table.aggregate([
      {$match:{_id:1}},
      {$unwind:"$coll"},
      {$match:{"coll.fieldA":{$gt:10},"coll.fieldB":{$lt:20}}},
      {$project:{"fieldA":"$coll.fieldA","fieldB":"$coll.fieldB"}}
    ])
    
    • 1
  3. Andrey Krupskii
    2020-10-01T00:18:18Z2020-10-01T00:18:18Z

    这个解决方案怎么样:

    let valueA, valueB;
    let A = 5, B = 10;
    
    YourCollectionName.findOne({sourceId: someValue}, function(err, exemplar){
      if (err) throw err;
      if (!exemplar) console.log('Not found');
      exemplar.objArr.map(function(obj){
        if(obj.fieldA < A && obj.fieldB > B){
          valueA = obj.fieldA;
          valueB = obj.fieldB;
        }
      })
    });

    • -1

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何停止编写糟糕的代码?

    • 3 个回答
  • Marko Smith

    onCreateView 方法重构

    • 1 个回答
  • Marko Smith

    通用还是非通用

    • 2 个回答
  • Marko Smith

    如何访问 jQuery 中的列

    • 1 个回答
  • Marko Smith

    *.tga 文件的组重命名(3620 个)

    • 1 个回答
  • Marko Smith

    内存分配列表C#

    • 1 个回答
  • Marko Smith

    常规赛适度贪婪

    • 1 个回答
  • Marko Smith

    如何制作自己的自动完成/自动更正?

    • 1 个回答
  • Marko Smith

    选择斐波那契数列

    • 2 个回答
  • Marko Smith

    所有 API 版本中的通用权限代码

    • 2 个回答
  • Martin Hope
    jfs *(星号)和 ** 双星号在 Python 中是什么意思? 2020-11-23 05:07:40 +0000 UTC
  • Martin Hope
    hwak 哪个孩子调用了父母的静态方法?还是不可能完成的任务? 2020-11-18 16:30:55 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    Arch ArrayList 与 LinkedList 的区别? 2020-09-20 02:42:49 +0000 UTC
  • Martin Hope
    iluxa1810 哪个更正确使用:if () 或 try-catch? 2020-08-23 18:56:13 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5