Mongo查询具有两级未知父键的嵌套字段值

2024-05-06

我们使用 MongoDB 来存储时间序列传感器数据,类似于设计中所示的模式https://www.mongodb.com/blog/post/schema-design-for-time-series-data-in-mongodb https://www.mongodb.com/blog/post/schema-design-for-time-series-data-in-mongodb

我们确实在不同时间段的数据查询上获得了良好的性能。 对我们的架构设计的说明:"v"是传感器读数的父键,时间使用分钟和秒转换为嵌套数组。我们用"m"(分钟)作为子父键,然后"s"(二)作为分钟阅读的子键。传感器读数位于"s"field1, field2, ...,field10作为传感器数据值。

现在我们正在尝试实现一些数据分析设施,并希望通过传感器数据读取值来查询数据。有没有一种有效的方法可以在查询中不使用嵌套 for 循环的情况下查询数据?

例如:

  1. 有传感器读数的物品:“字段1”>2
  2. 有传感器读数的物品:“字段1”>2 and “字段3”>5

太感谢了。

这些记录类似于下面的示例。

{
   "_id": ObjectId("5a5dd49f74bbaefd1ac89fc8"),
   "c_id": "1017",
   "c_id_s": NumberInt(1017),
   "c_t": NumberInt(1516096800),
   "type": "hour",
   "v": {
     "m1": {
       "s54": {
         "field1": 7.373158,
         "entry_id": NumberInt(4635),
         "field3": 0.19,
         "field2": NumberInt(88) 
      } 
    },
     "m31": {
       "s54": {
         "field1": 5.981918,
         "entry_id": NumberInt(4637),
         "field3": 0.04 
      },
       "s55": {
         "field2": NumberInt(89),
         "entry_id": NumberInt(4639),
         "field5": NumberInt(-67) 
      } 
    } 
  },
   "entry_id": NumberInt(4639) 
}, 
{
   "_id": ObjectId("5a5dd1a174bbaefd1ac89fc1"),
   "c_id": "1024",
   "c_id_s": NumberInt(1024),
   "c_t": NumberInt(1516096800),
   "type": "hour",
   "v": {
     "m3": {
       "s22": {
         "field3": 210.479996,
         "entry_id": NumberInt(30297) 
      },
       "s23": {
         "field1": 3.271534,
         "entry_id": NumberInt(30300),
         "field8": 7.1875,
         "field2": NumberInt(94) 
      } 
    },
     "m8": {
       "s23": {
         "field3": 150.639999,
         "entry_id": NumberInt(30304),
         "field1": 2.948425,
         "field8": 7.125,
         "field2": NumberInt(94) 
      } 
    },
     "m13": {
       "s23": {
         "field3": 99.799995,
         "entry_id": NumberInt(30308),
         "field1": 2.849621,
         "field8": 7.0625,
         "field2": NumberInt(95) 
      } 
    },
     "m18": {
       "s23": {
         "field3": 59.099998,
         "entry_id": NumberInt(30312),
         "field1": 2.681393,
         "field8": 6.9375,
         "field2": NumberInt(95) 
      } 
    },
     "m19": {
       "s8": {
         "field5": NumberInt(-87),
         "entry_id": NumberInt(30313) 
      } 
    } 
  },
   "entry_id": NumberInt(30313) 
}

Mapreduce 允许您处理命名键,但聚合是高效查询的方法。

您必须将数据建模为聚合框架的嵌入文档数组。

我给你提供了两种选择。您可以针对您的数据集测试它们,看看哪一个更适合您。

就像是

"v":[
  {
    "minute":1,
    "seconds":[
      {
        "second":54,
        "data":{
         "field1":7.373158,
         "entry_id":4635,
         "field3":0.19,
         "field2":88
       }
      }
    ]
  },
  {
    "minute":2,
    "seconds":...
  }
]

现在您可以轻松查询具有传感器读数的项目:“field1”>2。

db.col.aggregate(
  [{"$match":{"v.seconds.data.field1":{"$gt":2}}},
   {"$unwind":"$v"}, 
   {"$match":{"v.seconds.data.field1":{"$gt":2}}},
   {"$unwind":"$v.seconds"}, 
   {"$match":{"v.seconds.data.field1":{"$gt":2}}},
   {"$project":{"data":"$v.seconds.data"}}]
)

或者,您可以按分钟拆分文档。就像是

"v":[
  {
    "second":1,
    "data":{
       "field1":7.373158,
       "entry_id":4635,
       "field3":0.19,
       "field2":88
     }
  },
  {
     "second":2,
     "data":...
  }
]

您现在可以像这样查询(使用 v.data.field1 上的索引)

db.col.aggregate(
  [{"$match":{"v.data.field1":{"$gt":2}}},
   {"$unwind":"$v"}, 
   {"$match":{"v.data.field1":{"$gt":2}}},
   {"$project":{"data":"$v.data"}}]
)

您可以查询具有传感器读数的项目:“field1">2 和“field3">5

使用第一个结构

db.col.aggregate(
  [{"$match":{"v":{"$elemMatch":{"seconds": {$elemMatch:{"field1":{$gt":2},"field3":{$gt":5}}}}}}},
  {"$unwind":"$v"}, 
    {"$match":{"v.seconds": {$elemMatch:{"field1":{$gt":2},"field3":{$gt":5}}}}},
  {"$unwind":"$v.seconds"}, 
  {"$project":{"data":"$v.seconds.data"}}]
)

使用第二种结构

db.col.aggregate(
  [{"$match":{"v.data":{$elemMatch:{"field1":{$gt":2},"field3":{$gt":5}}}}},
  {"$unwind":"$v"}, 
  {"$match":{"v.data.field1":{"$gt":2},"v.data.field3":{"$gt":5} }},
  {"$project":{"data":"$v.data"}}]
)

蒙戈更新3.6

$match with $expr它接受聚合表达式。

$gt > 0- 聚合表达式,用于检查一分钟内所有匹配秒标准的总和是否大于 0

$objectToArray将命名键转换为键值对,然后$filter输入条件的秒数和匹配秒记录的输出编号。

db.testcol.aggregate(
{"$match":{
  "$expr":{
    "$gt":[
      {"$sum":{
        "$map":{
          "input":{"$objectToArray":"$v"},
          "as":"secondsofminute",
          "in":{
            "$size":{
              "$filter":{
                "input":{"$objectToArray":"$$secondsofminute.v"},
                "as":"seconds",
                "cond":{"$gt":["$$seconds.v.field2",2]}
              }
            }
          }
        }
      }},
    0]
  }
}})

Mongo 更新 3.4 - 替换$expr with $redact

db.col.aggregate(
 {"$redact":{
  "$cond":{
    "if":{
      "$gt":[
        {"$sum":{
          "$map":{
            "input":{"$objectToArray":"$v"},
            "as":"secondsofminute",
            "in":{
              "$size":{
                "$filter":{
                  "input":{"$objectToArray":"$$secondsofminute.v"},
                  "as":"seconds",
                  "cond":{"$gt":["$$seconds.v.field2",2]}
                }
              }
            }
          }
        }},
        0]
    },
   "then":"$$KEEP",
   "else":"$$PRUNE"
  }
}})
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Mongo查询具有两级未知父键的嵌套字段值 的相关文章

  • 如何使用 node.js / mongodb 在 HTML 中显示任意、无模式数据

    我使用 mongodb 将应用程序错误日志存储为 json 文档 我希望能够将错误日志格式化为 HTML 而不是将纯 json 返回到浏览器 日志是完全无模式的 它们可以随时更改 因此尝试执行此操作 在 Jade 中 是没有用的 var i
  • $lookup结果中的$match

    我有下一个蒙戈代码 db users aggregate match and UserName eq administrator Company CompanyName eq test lookup from companies local
  • 在 MongoDB 中,如何根据嵌入对象中的属性对文档进行排序?

    在我的产品集合中 我可以找到已在 GB 地区发布的所有产品 gt db products find release region GB pretty id foo release region GB date ISODate 2012 03
  • MongoDB 在仅返回 _id 时使用 COLLSCAN

    我想返回 MongoDB 集合中的所有 ID 我使用了以下代码 db coll find id 1 但MongoDB扫描整个集合而不是从默认读取信息index id 1 从日志中 find collection filter project
  • CoreMongooseArray 到普通数组

    我正在从一个架构中选出 2 个元素 并希望在另一个架构中进行更新 为此 我使用切片方法将数组中的前 2 个元素列入候选名单 但我越来越 CoreMongooseArray 元素1 元素2 而不是 元素1 元素2 如何删除 CoreMongo
  • 加密 mongodb 中的密码字段

    我有以下代码 它插入userName and password进入数据库 但密码以纯文本格式存储 我的意思是 当我查看数据库时 我可以看到插入的密码 我想存储password in encrypted format MongoClient
  • 当字段不为空时创建部分索引

    我正在尝试在字段上创建部分索引 但仅当该字段不为空时 换句话说 我希望能够让许多文档能够存储 null 但对于在字段中实际具有值的文档 我希望该值是唯一的 这是我尝试使用的代码 db account createIndex email 1
  • 嵌入文档中的mongodb限制

    我需要创建一个消息系统 一个人可以在其中与许多用户进行对话 例如 我开始与 user2 user3 和 user4 交谈 因此他们中的任何人都可以看到整个对话 并且如果对话在任何时候都不是私密的 则任何参与者都可以将任何其他人添加到对话中
  • Node.js 重用 MongoDB 参考

    我无法理解 Node js 例如 MongoDB 访问 这是我得到的 mydb js var mongodb require mongodb server new mongodb Server staff mongohq com 10030
  • MONGODB [DEBUG] 游标的cursor.refresh() 7078636577051629992

    更新大型 json 列表时 出现以下错误 2012 04 01T09 34 00 00 00 app run 1 MONGODB DEBUG cursor refresh for cursor 7078636577051629992 201
  • 让 MongoDB 在 Linux 上监听远程连接

    我已在 Windows 本地计算机上 上成功安装 MongoDB 作为服务 但现在我想将 MongoDb 移动到单独的服务器 所以我将 tarball 解压到网络上的虚拟服务器 运行 Linux 当我从本地计算机使用 PuTTY 连接到服务
  • 如何解决:“MongoError:此图集层不允许使用 $where”?

    使用 MongoDB Atlas 时如何解决 MongoError where is not allowed in this atlas tier 这是我的代码 async function getEventsTakingPlace con
  • Mongodb 数据建模/投票更新(向上和向下)

    Mongo 中有一个关于投票数据模型 更新查询的示例 http www mongodb org display DOCS MongoDB Data Modeling and Rails MongoDBDataModelingandRails
  • ReferenceError:MongoDB shell 中未定义 require

    我尝试通过 Windows 命令 Windows 8 1 从 Mongo 客户端连接 MongoDB 当我使用require 在 javascript 中 我遇到如下错误 有人有同样的问题吗 我有错过任何一个吗require有关的npm安装
  • Mongodb 聚合中对数组元素求和

    我有以下收藏c每个文档内的数组 id 1 k 2 2 type dog c parentId 1 p 2 2 parentId 1 p 1 4 id 2 k 4 3 type cat c parentId 2 p 5 2 parentId
  • MongoDB:如果使用 $addToSet 或 $push,是否应该预先分配文档?

    我一直在研究 MongoDB 我知道强烈建议在插入时完全构建 预分配 文档结构 这样将来对该文档的更改不需要移动该文档磁盘周围 这在使用 addToSet 或 push 时适用吗 例如 假设我有以下文档 id rsMH4GxtduZZfxQ
  • 将日期差转换为年数以计算 MongoDB 中的年龄

    我正在使用以下方法来计算时间戳差异中的年龄 db getCollection person aggregate project item 1 DOB personal DOB dateDifference subtract new Date
  • Mongodb:语法错误:意外的标识符

    我是 mongodb 的新手 我正在使用 mongolab 创建免费数据库 我的数据库名称是 enron 使用在线 mongoshell 连接到 mongo 数据库然后发生错误 mongo ds033499 mongolab com 334
  • Express中间件修改请求

    我目前有一个正在运行的服务器 前端使用nodejs mongo express 和 W2UI W2ui 请求来自包含所有参数的记录数组 记录 名称 foo 我想编写一个中间件 在请求到达路由之前对其进行编辑和更改 您可以创建自己的中间件来处
  • pymongo复制辅助读取引用不起作用

    我们有 MongoDB 2 6 和 2 副本集 并且我们使用pymongo驱动程序并使用以下 url 连接 Mongodb 副本集 mongodb admin email protected cdn cgi l email protecti

随机推荐

  • 为什么 getSession() 在短时间内间隔的后续请求中不返回相同的会话?

    我正在发送一个 getJSON HTTP GET 请求两次 使用不同的数据 一次又一次 假设我们有 request1 和 request2 我可以在 FF 和 Chrome 的开发者工具中看到我有相同的cookie JSESSIONID F
  • 使用 leaflet.js 在点周围添加设定大小的正方形多边形

    有点奇怪 希望有人能帮忙 在传单中 一旦用户输入了纬度 经度并向地图添加了一个点 我希望能够在该点周围添加一个 10 公里的正方形 我尝试四处寻找计算方法来找到 x 公里外的正方形角点 但没有挖出任何东西 但肯定有更简单的方法 有人有想法吗
  • 如何在 Django 中创建多选框?

    我正在尝试创建多选框字段来自姜戈选择 2 https github com applegrew django select2库如下图所示 我使用了下一个代码 但它返回简单的选择多个小部件 我想我忘了补充一些东西 我的错误在哪里 有人可以告诉
  • 使用 stringstreams 将字符串转换为 __uint128_t

    我正在尝试从字符串中提取不同类型的数据 void readHeader char buf BUFFSIZE std istringstream hdr buf uint128 t id client hdr gt gt id client
  • C++:初始化结构体并设置函数指针

    我正在尝试使用函数指针初始化结构 但是除非使用全局函数完成 否则我很难这样做 以下代码有效 float tester float v return 2 0f v struct MyClass Example typedef float My
  • 为什么 Visual Studio 2019 不会运行我的单元测试?

    我在 VS2019 中看到 NUnit 测试的一些非常奇怪的行为 而相同的解决方案在 VS2017 中运行良好 我的脑海里有几个 NUnit 测试项目 在安装了 NUnit Runner 扩展的 VS2017 中 我可以在 测试资源管理器
  • 使用 java 执行 Matlab 函数

    我正在编写一个应用程序 它使用 matlab 进行图像处理 然后使用 Java 接口显示结果 由于某些原因 我必须同时使用 Java 和 Matlab 如何在java中使用matlab函数 如何创建和访问界面 MATLAB控制 http m
  • 有没有办法通过 Outlook API 获取建议的联系人?

    我目前正在开发一个应用程序来获取我的 Microsoft 帐户中的联系人 问题是 与 Google 不同 当我向新联系人发送电子邮件或从新联系人接收电子邮件时 该电子邮件不会复制到 我的联系人 中 因此我无法通过该电子邮件https out
  • 如何修复 Visual Studio Code 终端中的“分段错误”错误?

    在 Windows 10 上 我安装了 Visual Studio Code 当我打开终端 Git Bash 并输入less watch compiler 我收到错误 分段故障 但是如果我转到 Git Bash 终端本身 在 Visual
  • 重新创建 Siri 按钮发光动画

    有没有办法复制 Siri 按钮发光动画 它看起来绝对华丽 但我现在不知道如何开始 是否有在线预格式化的旋转PNG 或者是用CoreAnimation完成的 我相信 Siri 动画是用 CAEmitterLayer 和 CAEmitterCe
  • 渲染脚本渲染在Android上比OpenGL渲染慢很多

    背景 我想根据Android相机应用程序的代码添加实时滤镜 但Android相机应用程序的架构是基于OpenGL ES 1 x 我需要使用着色器来自定义我们的过滤器实现 然而 将相机应用程序更新到OpenGL ES 2 0太困难了 然后我必
  • 查询不可更新

    我正在尝试使用 BE SQL Server 2012 Express 中的记录更新本地 Access 2007 表 我的步骤在这里 SQL Server中存在带有4个参数的存储过程来获取所需的记录 Access VBA中有调用SP并进行临时
  • BitBucket+Jenkins:仅在特定分支更改时触发构建

    以下是该问题的据称解决方案 尽管它看起来确实是一种解决方法 而不是最终的解决方案 有没有一种方法 通过作业配置或 bitbucket 挂钩配置 我可以将作业设置为仅在推送到特定分支时运行构建 是否可以仅从一个特定分支触发 Jenkins h
  • PySide2/QML 填充 Gridview 模型/委托并为其设置动画

    我是 QML 的新手 正在寻求以下几点帮助 如何基于 TextField 输入 如 Regex 通过 PySide2 过滤 Gridview 模型中的 QAbstractListModel 数据 标题 如何在鼠标悬停时为 Gridview
  • Spark:Aggregator和UDAF有什么区别?

    在Spark的文档中 Aggregator 抽象类聚合器 IN BUF OUT 扩展可序列化 用户定义聚合的基类 可以是 在数据集操作中用于获取组中的所有元素并 将它们减少到单个值 用户定义的聚合函数是 抽象类 UserDefinedAgg
  • JavaScript:发送 POST,重定向到响应

    我有一个带有 onclick 的图像 当单击事件触发时 我想发送 HTTP POST 并将 window location 重定向到 POST 的响应 我怎样才能做到这一点 只需将按钮绑定到表单元素的提交方法 重定向就会自然发生
  • 如何将NSDate转换为unix时间戳iphone sdk?

    如何转换NSDate转换为 Unix 时间戳 我读过很多相反的帖子 但我没有找到与我的问题相关的任何内容 我相信这是您正在寻找的 NSDate 选择器 NSTimeInterval timeIntervalSince1970
  • Struts 2 中的 Java 应用程序可以管理多少个会话?

    我正在开发事务管理应用程序 并且正在使用 Struts2 我在内部使用了一个会话来设置和获取值 例如 ActionContext getContext getSession put string string 在应用程序中使用这样的会话是否
  • 如何在这个可嵌套的 For 循环中实现 Robot Framework 风格的变量?

    我在 Robot Framework 中见过很多 嵌套 For 循环 主要是创建一个内部带有 For 循环的关键字 然后在另一个 For 循环中调用该关键字 我使用 Python 2 7 13 制作了一个可嵌套的 For 循环 但因为它主要
  • Mongo查询具有两级未知父键的嵌套字段值

    我们使用 MongoDB 来存储时间序列传感器数据 类似于设计中所示的模式https www mongodb com blog post schema design for time series data in mongodb https