【问题标题】:How to query nested documents in MongoDB?如何在 MongoDB 中查询嵌套文档?
【发布时间】:2018-10-06 08:18:37
【问题描述】:

我对数据库和 MongoDB 非常陌生。我尝试将财务报表信息存储在数据库中,每个文档代表一家公司。

我已经创建了一个嵌套文档(可能不是一个好方法),如下图。最外层包含Annual statement、Basic info、Key Map和Interim Statement。在年度报表中,有不同的日期。在日期内,我们有不同类型的语句(INC、BAL、CAS),然后内部级别包含真实数据。

我的问题是如何查询数据库以给我所有包含 2017 语句的文档(例如)?

现在的年份格式为 YYYY-MM_DD。但我只想过滤 YYYY。

【问题讨论】:

  • 是 INC 属性固定字段名称 (SREV,RTLR, ...) 。你都知道吗?
  • 是的。我有一张地图,它告诉我名称代表什么字段。这实际上存储在“键映射”中。

标签: mongodb


【解决方案1】:

我非常不鼓励使用变量(此处为日期,INC)作为字段名称。查询,更新将(更多)困难,您不能使用索引。所以在大多数情况下这是一个非常糟糕的主意,即使在少数静态值(INC、BAL、CAS)的情况下它可以是“可接受的”(但不好的做法)。

我的建议是更改您的架构以使其更易于使用,例如:

[
  {
    "annual_statement": [
        { "date": ISODate("2017-12-31"),
          "INC":{
              "SREV": 1322.5,
              "RTLR": 1423.4,
              ...
            },
          "BAL":{...},
          "CAS":{...}
        },
      {   "date": ISODate("2017-12-31"),
          "INC":{
              "SREV": 1322.5,
              "RTLR": 1423.4,
              ...
            },
          "BAL":{...},
          "CAS":{...}
        }
    ]
  }
]

要查询此架构,请使用以下命令:

db.collection.find({
  "annual_statement": {
    $elemMatch: {
      date: {
        $lt: ISODate("2018-01-01"),
        $gte: ISODate("2017-01-01"),

      }
    }
  }
})

将至少在 2017 年的日期归还给您完整的文件。

添加如下投影只会返回匹配的年度报表:

db.collection.find({
  "annual_statement": {
    $elemMatch: {
      date: {
        $lt: ISODate("2018-01-01"),
        $gte: ISODate("2017-01-01"),

      }
    }
  }
},
{
  "annual_statement": {
    $elemMatch: {
      date: {
        $lt: ISODate("2018-01-01"),
        $gte: ISODate("2017-01-01"),

      }
    }
  }
})

【讨论】:

  • 为什么有时我们使用列表,有时使用字典?我可以用 "annual_statement":{ } 代替 [ ]
  • 逻辑问题:你有一个语句列表,你使用数组作为语句。并且使用对象(或字典)会强制您使用变量作为字段名称,并且不要忘记您不能查询字段名称,而只能查询字段值。
  • 现在,我已经修改了架构。例如,如何查询 2017 年的所有语句?
【解决方案2】:

使用 $exists (注意我使用的是 python - 下面是 pymongo 驱动程序语法 - 你的可能不同) https://docs.mongodb.com/manual/reference/operator/query/exists/

示例:按公司查找所有“2017”“INC”记录。

year_exists=db.collection.find({'Annual.2017-12-31': {'$exists':True}})

for business in year_exists:
     bus_name = business['BasicInfo']['CompanyName']
     financials_INC = business['Annual']['2017-12-31']['INC'])
     print(bus_name, financials_INC)

【讨论】:

  • 这可行,但这不是 OP 所要求的......要求是仅通过“YYYY”“搜索”。
  • 感谢 Akrion 的输入。我假设“过滤器”声明无关紧要,因为报告是年度报告,所以关键可能是包含年份的任何内容。我实际上是在尝试回答这个问题,而不是解释如何更好地构建数据。我可能应该要求澄清。再次感谢。
猜你喜欢
  • 2018-03-09
  • 2021-02-25
  • 2016-08-16
  • 2023-03-08
  • 1970-01-01
  • 2021-11-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多