在猫鼬中使用聚合搜索进行分页

时间:2021-02-02 10:57:08

标签: node.js mongoose

const page = 1;
const limit = 10;

const searchResultsArray = await mongoose.connection.db
                .collection('game_activity')
                .aggregate([
                    {
                        $match: {
                            game_id
                        }
                    },
                    {
                        $addFields: {
                            activities: {
                                $filter: {
                                    input: '$activity',
                                    as: 'activity',
                                    cond: {
                                        $and: condition
                                    }
                                }
                            }
                        }
                    },
                    {
                        $project: {
                            activities: 1,
                            activity_number: { <--- can't read property error
                                $size: '$activities'
                            }
                        }
                    },
                    { $limit: 50 },
                    {
                        $facet: {
                            paginatedResult: [ { $sort: searchFilter }, { $skip: (page - 1) * limit } ]
                        }
                    }
                ])
                .toArray();
            const searchResultsObject = searchResultsArray[0];
            if (
                searchResultsObject.paginatedResult[0].activity_number === undefined ||
                searchResultsObject.paginatedResult[0].activity_number == 0
            ) {
                const result = {
                    no_activities: true
                };
                res.json(result);
            } else {
                const result = {
                    search_result: {
                        total_activities: searchResultsObject.paginatedResult[0].activity_number,
                        current_page: page,
                        last_page: Math.ceil(searchResultsObject.paginatedResult[0].activity_number / 10),
                        searched_activities: searchResultsObject.paginatedResult[0].activities
                    },
                    no_activities: false
                };
                res.json(result);
            }

我有这个 .aggregate() 搜索功能并尝试应用分页结果。此格式适用于其他搜索,但在此 aggregate() 搜索中,我遇到了 2 个问题。

console.log(searchResultsObject.paginatedResult[0]); 
-------- result --------
{
  search_result: {
    total_activities: 16,
    current_page: 1,
    last_page: 2,
    searched_activities: [
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object],
      [Object], [Object]
    ]
  },
  no_activities: false
}
  1. const limit = 10 不适用于此处。它返回所有的 activities

  2. 当我设置 const page = 2; 时,我收到 TypeError: Cannot read property 'activity_number' of undefined 这个错误并且 console.log(searchResultsObject.paginatedResult[0]); 显示 `undefined

我想每页返回 10 个游戏活动,因此在这种情况下,如果我设置 const page =2;,那么它将返回其余 6 个 activities。我不太清楚如何解决这个问题,因为这适用于我拥有的其他 .aggregate() 搜索。

------------ MongoDB 文档 ---------

{
    "_id": {
        "$oid": "601942d93aca6ee8cb300327"
    },
    "location_id": "ddff23323443",
    "activity": [{
        "activity_id": "VVINxmhRHsnMwvfT",
        "created_by": {
            "id": "aa332",
           
        },
        "activity_type": "league_of_legends",
        "activity_info": {
            "location_id": "ddff23323443",
            "activity_time": "2021-02-02 05:45:00.000Z",
            "game_code": "6"
        },
        "attendee": ["aa332"]
    }, {
        "activity_id": "EBZNKmsFKDgdeDz0",
        "created_by": {
            "id": "aa332",
           
        },
        "activity_type": "league_of_legends",
        "activity_info": {
            "id": "ddff23323443",
            "activity_time": "2021-02-02 05:45:00.000Z",
            "game_code": "6"
        },
        "attendee": ["aa332"]
    }, {
        "activity_id": "j8J1Jlk8MtWPi1HT",
        "created_by": {
            "id": "aa332",
           
        },
        "activity_type": "league_of_legends",
        "activity_info": {
            "location_id": "bvvsd33",
            "activity_time": "2021-02-02 05:45:00.000Z",
            "game_code": "6"
        },
        "attendee": ["aa332"]
    }]
}

-----期待-----

const page = 1
 {
      search_result: {
        total_activities: 16,
        current_page: 1,
        last_page: 2,
        searched_activities: [
          [Object], [Object],
          [Object], [Object],
          [Object], [Object],
          [Object], [Object],
          [Object], [Object],
        ]
      },
      no_activities: false
    }

const page = 2
 {
      search_result: {
        total_activities: 16,
        current_page: 2,
        last_page: 2,
        searched_activities: [
          [Object], [Object],
          [Object], [Object],
          [Object], [Object],
        ]
      },
      no_activities: false
    }

1 个答案:

答案 0 :(得分:1)

根据您的尝试,您的期望并不明确,我可以解释基本的分页过程,

  • 分页配置
const page = 1;
const limit = 10;
// If you are starting page number from 1 then you need to minus 1
const skip = (page - 1) * limit;
  • $unwind 解构 activities 数组
  • $replaceRootactivities 对象替换为 root
  • $sort 个文档
  • $facet 将结果、结果数据和计数分开,$skip 应该在 $limit 之前
const searchResultsArray = await mongoose.connection.db.collection('game_activity').aggregate([
  { $match: { _id: game_id } },
  {
    $project: {
      activities: {
        $filter: {
          input: '$activity',
          as: 'activity',
          cond: { $and: condition }
        }
      }
    }
  },
  { $unwind: "$activities" },
  { $replaceRoot: { newRoot: "$activities" } },
  { $sort: searchFilter },
  {
    $facet: {
      searched_activities: [
        { $skip: skip },
        { $limit: limit }
      ],
      total_activities: [
        { $count: "count" }
      ]
    }
  }
]).toArray();
  • 无数据验证响应
// No Data Fond!
if (!searchResultsArray[0].total.length) {
  res.json({ no_activities: true });
  return;
}
  • 成功响应
res.json({
  search_result: {
    total_activities: searchResultsArray[0].total_activities[0].count,
    current_page: page,
    last_page: Math.ceil(searchResultsArray[0].total_activities[0].count / limit),
    searched_activities: searchResultsArray[0].searched_activities
  },
  no_activities: false
});
<块引用>

将上面的代码依次组合起来试试。