как посчитать длину агрегата перед пропуском (пагинацией) - PullRequest
0 голосов
/ 21 октября 2019

Я создаю API для получения подробной информации о рабочих местах, и мне нужно сделать нумерацию страниц для негоДля нумерации страниц мне нужно получить общее количество страниц, но я получаю только пропустить страницы. Пожалуйста, помогите мне получить общее количество страниц перед пропуском.

let cJobs = await CrewbiesJobs.GetAllJobs();
let flashJobsResult = [];
let totalPages = 0;
let filter = {};
let queryLimit = parseInt(req.query.limit) || 10;
let pageNo = parseInt(req.query.page) || 1;
let query = {};
if (pageNo < 0 || pageNo === 0) {
  throw new CustomError('invalid page number, should start with 1', HttpStatus.BAD_REQUEST);
}
query.skip = req.query.limit * (pageNo - 1) || 1;
query.limit = queryLimit;

let jobsAggregate = await Jobs.aggregate([{
    $lookup: {
      from: CrewbiesJobs.collection.name,
      localField: "jobId",
      foreignField: "jobId",
      as: "job_docs"
    }
  },
  {
    $unwind: "$job_docs"
  },

  {
    $project: {
      _id: 1,
      jobTitle: 1,
      jobId: 1,
      jobDescription: 1,
      postedDate: 1,
      filter1: 1,
      filter2: 1,
      filter3: 1,
      createdAt: 1,
      updatedAt: 1
    }
  },
  {
    $match: filter
  },
  {
    $skip: query.skip
  },
  {
    $limit: query.limit
  }


]).exec(function(err, doc) {
  if (err) {
    res.send(err);
  } else {
    totalPages = Math.ceil(doc.length / queryLimit);
    if (pageNo > totalPages) {
      throw new CustomError('Invalid page number', HttpStatus.BAD_REQUEST);
    }
    console.log('matched jobs ', doc.length);
    res.json({
      msg: 'Jobs listed successfully',
      item: {
        totalPages: doc.length,
        currentpage: pageNo,
        jobs: doc
      },
      jobsCount: doc.length
    });
  }
});
}
catch (err) {
  CustomError.Handle(err, res);
}

totalPages счетчик должен вернуть 21, но вместо этого я получаю только 10:

*{
  "msg": "Jobs listed successfully",
  "item": {
    "totalPages": 10,
    "currentpage": 1,
  },
  "jobsCount": 10
}*

Ответы [ 2 ]

1 голос
/ 21 октября 2019

Возможность совершить одну поездку к db и получить количество документов - использовать $facet, что позволяет обрабатывать несколько конвейеров агрегации. Поскольку $count не будет работать с $addFields или $project в сочетании с фактическим результатом конвейера.

Запрос: (После разматывания этапа job_docs do $facet)

Jobs.aggregate([
  {
    $lookup: {
      from: CrewbiesJobs.collection.name,
      localField: "jobId",
      foreignField: "jobId",
      as: "job_docs"
    }
  },
  {
    $unwind: "$job_docs"
  },
  {
    $facet: {
      totalDocs: [
        {
          $count: "value"
        }
      ],
      pipelineResult: [
        {
          $project: {
            _id: 1,
            jobTitle: 1,
            jobId: 1,
            jobDescription: 1,
            postedDate: 1,
            filter1: 1,
            filter2: 1,
            filter3: 1,
            createdAt: 1,
            updatedAt: 1
          }
        },
        { $match: filter },
        { $skip: query.skip },
        { $limit: query.limit }
      ]
    }
  },
  { $unwind: "$totalDocs" }
]).exec();

Результирующий документ: Демо

{
  "totalDocs" : {
          "value" : 44
  },
  "pipelineResult" : [
          {
                  "_id" : ObjectId("5da7040e45abaee927d2d11a"),
                  "jobTitle" : "Foo",
                  "jobDescription": "Bar",
                  ...
                  "job_docs" : {...}
          },
          ...
  ]
}

Где totalDocs содержит количество документов в свойстве value, а pipelineResult будет содержать документы основных операций конвейера.

0 голосов
/ 21 октября 2019

Насколько я знаю, вам нужно иметь отдельный запрос для общего количества.

Обе агрегации имеют общие этапы, поэтому сначала я создал baseStages. Затем я добавил этапы пропуска и ограничения к этому базовому этапу для данных заданий и добавил этап подсчета к базовому этапу, чтобы получить общее количество сборов.

Таким образом, вы можете попробовать что-то вроде этого:

const baseStages = [
  {
    $lookup: {
      from: CrewbiesJobs.collection.name,
      localField: "jobId",
      foreignField: "jobId",
      as: "job_docs"
    }
  },
  {
    $unwind: "$job_docs"
  },

  {
    $project: {
      _id: 1,
      jobTitle: 1,
      jobId: 1,
      jobDescription: 1,
      postedDate: 1,
      filter1: 1,
      filter2: 1,
      filter3: 1,
      createdAt: 1,
      updatedAt: 1
    }
  },
  { $match: filter }
];

const jobsStages = [
  ...baseStages,
  { $skip: query.skip },
  { $limit: query.limit }
];

let jobsAggregate = await Jobs.aggregate(jobsStages);

const countStages = [...baseStages, { $count: "COUNT" }];

let countAggregate = await Jobs.aggregate(countStages);

Чтобы построить ответ, я должен был указать console.log (countAggregate), проверить, где находится значение счетчика, и использовать это значение в ответе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...