【问题标题】:How can I optmize this query in mongodb?如何优化 mongodb 中的查询?
【发布时间】:2022-09-30 23:49:35
【问题描述】:

这是完整的查询:

  async getHistoryByTag(context: StandardContext) {
    const { mongo } = context.state;
    const tag = context.params.tag.replace(/-+/g, \" \");
    const today = new Date();
    const prevSunday = getOneWeekAgo(today);

    console.log(\"today: \", today, \"prev sunday: \", prevSunday);

    const all = await mongo
      .collection(\"search_history\")
      .aggregate<SearchHistoryModel & { username: string; word: string }>([
        {
          $match: {
            created_at: { $gt: prevSunday.toISOString() },
          },
        },
        {
          $lookup: {
            from: \"users\",
            localField: \"user_id\",
            foreignField: \"id\",
            as: \"user\",
            pipeline: [
              {
                $project: {
                  username: 1,
                },
              },
            ],
          },
        },

        // { search_id: 1, created_at: 1, url: 1 }
        {
          $lookup: {
            from: \"positive\",
            localField: \"search_id\",
            foreignField: \"search_id\",
            as: \"positive\",
            pipeline: [
              {
                $project: {
                  word: 1,
                },
              },
            ],
          },
        },
        {
          $unwind: {
            path: \"$user\",
            preserveNullAndEmptyArrays: true,
          },
        },
        {
          $unwind: {
            path: \"$positive\",
            preserveNullAndEmptyArrays: true,
          },
        },
        {
          $replaceRoot: {
            newRoot: {
              $mergeObjects: [\"$$ROOT\", \"$user\", \"$positive\"],
            },
          },
        },
        {
          $match: {
            word: tag,
          },
        },
        {
          $project: {
            user: 0,
            positive: 0,
          },
        },
        {
          $sort: {
            created_at: -1,
          },
        },
      ])
      .toArray();

    context.response.body = all.filter((value, index, self) => {
      return self.findIndex((v) => v.url === value.url) === index;
    });
  }

我尝试添加索引,但仍需要 5-10 秒才能响应。

  • 还请显示集合上的索引和 mongodb 正在使用的查询计划(运行解释)。每个集合中的文档数量肯定会与机器的 RAM 一起提供帮助。
  • 我为explain 运行什么命令?机器有 64gb 内存
  • &gt; db.search_history.explain(\'allPlansExecution\') Explainable(grazily.search_history

标签: node.js mongodb deno


【解决方案1】:

您只需要稍微重新排序 mongo 管道。

match 和 sort 应该首先使用索引,也不要在根管道中使用填充属性的匹配,而是在填充管道中使用。

所以,你的管道应该是这样的。

    const all = await mongo
      .collection("search_history")
      .aggregate<SearchHistoryModel & { username: string; word: string }>([
        // match should be first
        {
          $match: {
            created_at: { $gt: prevSunday.toISOString() },
          },
        },
        // sort should be second
        {
          $sort: {
            created_at: -1,
          },
        },
        {
          $lookup: {
            from: "users",
            localField: "user_id",
            foreignField: "id",
            as: "user",
            pipeline: [
              {
                $project: {
                  username: 1,
                },
              },
            ],
          },
        },
        {
          $lookup: {
            from: "positive",
            localField: "search_id",
            foreignField: "search_id",
            as: "positive",
            pipeline: [
              {    
                $match: {word: tag},   // move the populated match inside the populate pipeline to use the index
              }
              {
                $project: {
                  word: 1,
                },
              },
            ],
          },
        },
        {
          $unwind: {
            path: "$user",
            preserveNullAndEmptyArrays: true,
          },
        },
        {
          $unwind: {
            path: "$positive",
            preserveNullAndEmptyArrays: true,
          },
        },
        {
          $replaceRoot: {
            newRoot: {
              $mergeObjects: ["$$ROOT", "$user", "$positive"],
            },
          },
        },
        {
          $project: {
            user: 0,
            positive: 0,
          },
        },
      ])
      .toArray();

注意:如果您的收藏量很大,请使用分页来加快查询速度。

【讨论】:

  • 这对我来说似乎是正确的答案。确保positive 集合具有类似{ word: 1 } 的索引
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-25
  • 1970-01-01
  • 2015-01-21
  • 2015-01-09
  • 2015-03-06
  • 1970-01-01
  • 2021-04-28
相关资源
最近更新 更多