【问题标题】:Mongodb aggregate: How to slice a result of type array of object?Mongodb聚合:如何切片对象类型数组的结果?
【发布时间】:2021-10-13 04:00:07
【问题描述】:

我有一个返回对象数组的聚合查询。我试图通过在管道末尾添加这个阶段来分割它:

  let limit = 5;
  let skip = limit * 1;
  const page_limit_stage = {
    $project: {
      profiles: {
        $slice: ["$$CURRENT", skip, limit],
      },
    },
  };

但是,我不断收到此错误:

???? ~ 文件:profile.js ~ 第 331 行 ~ err MongoError: 第一个参数 $slice 必须是数组,但类型为:object

知道如何解决这个问题吗?


编辑 2:这是我正在使用的查询:

const filterProfiles = async function filterProfiles() {
  const { users_filter_option, profiles_filter_option } =
    prepareProfilesFilterSearchOptions();

  const profile_stage = {
    $lookup: {
      from: "profiles",
      let: { profile_id: "$profile" },
      pipeline: [profiles_filter_option],
      as: "profile",
    },
  };

  const profile_populate_options = [
    {
      $lookup: {
        from: "schema_name_1",
        localField: "profile.schema_name_1",
        foreignField: "_id",
        as: "schema_name_1",
      },
    },
    {
      $lookup: {
        from: "schema_name_2",
        localField: "profile.schema_name_2",
        foreignField: "_id",
        as: "schema_name_2",
      },
    },
  ];
  const project_stage = {
    $project: {
      user_id: "$_id",
      name: "$name",
      surname: "$surname",
      country: "$country",
      schema_name_2: { $arrayElemAt: ["$schema_name_2", 0] },
      schema_name_1: "$schema_name_1",
    },
  };
  let limit = 5;
  let skip = limit * 1;
  const page_limit_stage = {
    $project: {
      profiles: {
        $slice: ["$CURRENT", skip, limit],
      },
    },
  };
  const pipeline = [
    users_filter_option,
    profile_stage,
    ...profile_populate_options,
    { $unwind: "$profile" },
    project_stage,
    page_limit_stage,
  ];
  const users = await User.aggregate(pipeline);

  return users;
};

这是没有page_limit_stage的结果:

[
  {
    _id: "aegaeg",
    user_id: "aegaef",
    name: "user_name",
    surname: "user_surname",
    country: "country_name",
    schema_name_1: "value",
    schema_name_2: "value2",
  },
  // multiple documents like this
];

【问题讨论】:

  • 它说你的输入字段类型是一个对象但它需要一个数组,为什么$$,只尝试$?你能发布一个示例文档吗?
  • @turivishal 我在编辑中添加了信息

标签: mongodb mongoose mongodb-query aggregation-framework


【解决方案1】:

如果您的文档中有对象属性数组,切片将起作用,但在您的情况下,您需要进行分页,分页有两个阶段$skip$limit

  let limit = 5;
  let skip = limit * 1;
  const skip_stage = { $skip: skip };
  const limit_stage = { $limit: limit };
    
  const pipeline = [
    users_filter_option,
    profile_stage,
    ...profile_populate_options,
    { $unwind: "$profile" },
    project_stage,
    skip_stage, 
    limit_stage
  ];

【讨论】:

    【解决方案2】:

    "$$CURRENT" 是系统变量,这里的值与$$ROOT 相同 系统变量see here

    它们都将进入管道的文档作为价值。 如果收藏是这样的

    [{_id : 1 name : "john" addresses [..]} ...]

    $$CURRENT 将 = {_id : 1 name : "john" addresses [..]} 它是一个文档而不是数组,不能被切片。(它具有来自管道的文档的值,上面是它将获得的第一个值)

    我认为您只需要以下内容(而不是 $addresses 输入您的数组名称)

    {
        $project: {
          profiles: {
            $slice: ["$addresses", skip, limit],
          },
        },
      };
    

    如果你想切片 $$ROOT 文档,你应该先做 $ObjectToArray$slice 之后,但我认为你不想要这个。

    【讨论】:

    • 数组没有名字。查看我刚刚进行的编辑并提供更多详细信息
    猜你喜欢
    • 2021-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-28
    • 1970-01-01
    • 1970-01-01
    • 2017-07-14
    相关资源
    最近更新 更多