【问题标题】:Mongoose extract specific section of a big documentMongoose 提取大文档的特定部分
【发布时间】:2018-10-01 21:51:38
【问题描述】:

对于那些将来偶然发现这篇文章的人。使用的结果很简单,mongodb 中的 4.5mb 文档对于高效读/写来说太大了。我们找到了一种将文档大小减少到每个文档大约 0.2mb 的方法。 mongo 查询需要速度......不要让文档大小超过大约。 0.5mb


我在 mongodb 中有一小部分文档(大约 500 个),每个文档大小为 4-6mb。

该数据库用于体育赛事。

文档的架构看起来像(精简):

const schema = {
  _id: {type: String, default: uuidv1},
  layoutName: String,
  contests: [
    {
      externalId: String,
      thirdPartyEventId: String,
      name: String,
      rounds: [
        {
          _id: {type: String, default: uuidv1},
          thirdPartyId: String,
          externalId: String,
          heats: [
            {
              externalId: String,
              name: String,
              order: Number,
              categories: [
                {
                  key: String,
                  label: String,
                },
              ],
              runs: [
                {
                  thirdPartyId: String,
                  externalId: String,
                  name: String,
                  order: Number,
                },
              ],
            },
          ],
        },
      ],
    },
  ],
}

目前,该应用程序通过 _id 获取整个对象,然后使用 lodash 提取热量,但这需要相当长的时间(大约 400 毫秒),因为 doc 包含大量数据。

我正在尝试查看数据库层是否会更快,但是我的 mongo 查询技能有点生疏。我将如何使用猫鼬编写查询来提取文档的特定部分。我试图通过以下方式查询文档集合:

{
  "_id": "ead08850-c313-11e8-8f9a-f7563bcfbf40",
  "contests.externalId": "Timing1",
  "contests.rounds.externalId": "Timing5",
  "contests.rounds.heats.externalId": "Timing21"
}

但是响应是空的。

上面的对象是我需要获取热量的路径。我是不是以错误的方式接近它?

PS/ 目前要提取正确的热量:

const contest = find(event.contests, {externalId: contestId})
if (!contest) {
  return false
}
const round = find(contest.rounds, {externalId: roundId})
if (!round) {
  return false
}
return find(round.heats, {externalId: heatId})

【问题讨论】:

  • 您可以发布示例数据吗?您的 find 查询结构看起来没问题。
  • 查找查询工作得很好,查找大约需要 20 毫秒。最大的时间是从 mongodb 集合中提取巨大的 4.5mb 文档(平均 500 毫秒)。所以我想知道 mongodb 是否可以比后查询工作更快地过滤我需要的内容。
  • 您到底想获得哪一部分...仅限heats
  • 是的,但只有在上述“externalId”与提供的值相匹配的情况下,“heats”是一个包含许多加热的数组和一个包含许多“比赛”的数组中的许多“回合”的数组。我的lodash“查找”功能可以快速工作,但从数据库中提取完整文档是我正在努力改进的慢速链接

标签: mongodb mongoose


【解决方案1】:

尝试使用聚合然后 $filter 像这样:

db.collection.aggregate([
  {
    $match: {
      "_id": 1,
      "contests.rounds.heats.externalId": 5
    }
  },
  {
    $unwind: "$contests"
  },
  {
    $unwind: "$contests.rounds"
  },
  {
    $project: {
      "_id": 0,
      "contests": {
        $filter: {
          input: "$contests.rounds.heats",
          as: "item",
          cond: {
            $eq: ["$$item.externalId", 5]
          }
        }
      }
    }
  }
])

working here

【讨论】:

  • 这仍然需要后期查询工作,但还会返回完整文档中的所有预赛,其中包括其他轮次的预赛和其他比赛的轮次。
  • 你能发布你想要的exact 输出吗?
  • 根据我在这里使用的样本数据,我只看到一个热量:mongoplayground.net/p/yPj3UDiyhCg
  • 哇,这是一个了不起的工具!我拿了你的数据并对其进行了调整:mongoplayground.net/p/KmUeNaqn_68 我在样本数据中的目标是 1 个热量,其中:"_id":1 & "contests.externalId":2 & "contests.rounds.externalId":2 & "contests.rounds.heats.externalId": 5
  • 查看聚合示例是否有效。我也用演示更新了答案。
猜你喜欢
  • 2020-08-18
  • 2012-12-16
  • 2018-04-19
  • 1970-01-01
  • 2018-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多