如何使用mongoose同时从mongodb查找文档并获得它们的计数

gywdnpxw  于 2023-01-09  发布在  Go
关注(0)|答案(1)|浏览(196)

我的目标是在特定条件下从数据库中获取图书,但同时我也想得到它们的数量。下面是我的代码。这里我实现了分页,所以我使用限制()并跳过()只获取特定页面所需的数据。我正在对标题或作者字段进行正则表达式搜索,并为给定的流派选择文档。我也排序他们在升序或降序的基础上查询。

const getAllBooks = asyncHandler(async (req, res) => {
  const page = req.query.page === undefined ? 1 : req.query.page;
  const limit = 5;
  const skip = page * limit - limit;
  const allGenres = ["action", "drama", "sci - fi", "romance", "comedy"];
  const reqGenre =
    req.query.genre === "" ? allGenres : req.query.genre.split(",");
  const search = req.query.search === undefined ? "" : req.query.search;
  const searchBy =
    req.query.searchBy === "title"
      ? { title: { $regex: search, $options: "i" } }
      : { author: { $regex: search, $options: "i" } };
  const sort = req.query.sort === "asc" ? 1 : -1;
  let sortBy;
  if (req.query.sortBy === undefined) {
    sortBy = { title: sort };
  } else if (req.query.sortBy === "author") {
    sortBy = { author: sort };
  } else if (req.query.sortBy === "title") {
    sortBy = { title: sort };
  }
  const books = await Book.find(searchBy)
    .where("genre")
    .in(reqGenre)
    .sort(sortBy)
    .skip(skip)
    .limit(limit)
    .select("-createdAt -updatedAt -__v");
  const documents = await Book.find(searchBy)
    .where("genre")
    .in(reqGenre)
    .sort(sortBy)
    .count();
  const total = documents / limit;
  res.status(200);
  res.json({ books, total });
})

下面是我的模型

const mongoose = require("mongoose");

const LibrarySchema = mongoose.Schema(
  {
    //denotes the title of the book
    title: {
      type: String,
      required: true,
    },
    // denotes the author of the book
    author: {
      type: String,
      required: true,
    },
    genre: {
      type: [String],
      required: true,
    },
  },
  {
    timestamps: true,
  }
);
module.exports = mongoose.model("LibraryModel", LibrarySchema);

目前,我可以在两个单独的数据库调用中获得图书和它们的总数。但假设如果我们在数据库中有数千本图书,那么这个方法将非常昂贵。所以我想将这两个调用合并为一个,并在一次访问中获得结果。我试图得到一个解决方案,但无法找到任何。任何帮助都是感激的。提前感谢。

j8yoct9x

j8yoct9x1#

我认为可以使用$facet生成两个输出:

db.collection.aggregate([
  {
    "$match": {
      // your searchBy query here
  },
  {
    "$sort": {
      // your sortBy query here
    }
  },
  {
    "$facet": {
      "result": [
        {
          "$skip": // your skip
        },
        {
          "$limit": // your limit
        },
        {
          "$project": {
            // your select
          }
        }
      ],
      "count": [
        {
          "$count": "count"
        }
      ]
    }
  },
  {
    "$project": {
      "result": 1,
      "count": {
        "$arrayElemAt": [
          "$count",
          0
        ]
      }
    }
  }
])

例如here在quey中有预定义的值,您可以使用您创建的对象。
你可以通过你拥有的JS对象来改变聚合对象,应该可以正常工作。
用于动态创建查询的JS代码段:

// mock req to avoid problems
const req = {
    query: {
        genre: ""
    }
}

const page = req.query.page === undefined ? 1 : req.query.page;
const limit = 5;
const skip = page * limit - limit;
const allGenres = ["action", "drama", "sci - fi", "romance", "comedy"];
const reqGenre = req.query.genre === "" ? allGenres : req.query.genre.split(",");
const search = req.query.search === undefined ? "" : req.query.search;
let matchQuery = {"$match":{}}
const searchBy = req.query.searchBy === "title"
        ? matchQuery["$match"] = { title: { $regex: search, $options: "i" } }
        : matchQuery["$match"] = { author: { $regex: search, $options: "i" } };
matchQuery["$match"]["genre"] = {"$in": reqGenre}
const sort = req.query.sort === "asc" ? 1 : -1;
let sortBy;
if (req.query.sortBy === undefined) {
    sortBy = { title: sort };
} else if (req.query.sortBy === "author") {
    sortBy = { author: sort };
} else if (req.query.sortBy === "title") {
    sortBy = { title: sort };
}
const query = [matchQuery,
  {
    "$sort": sortBy
  },
  {
    "$facet": {
      "result": [
        {
          "$skip": skip
        },
        {
          "$limit": limit
        },
        {
          "$project": {
            "createdAt": 0,
            "-createdAt": 0,
            "-updatedAt": 0,
            "-__v": 0
          }
        }
      ],
      "count": [
        {
          "$count": "count"
        }
      ]
    }
  },
  {
    "$project": {
      "result": 1,
      "count": {
        "$arrayElemAt": [
          "$count",
          0
        ]
      }
    }
  }]

  console.log(JSON.stringify(query))

这段代码创建了查询si,您只需执行const result = await Book.aggregate(query)即可。
注意console.log()输出是如何在this example中成为有效的Mongo查询的

相关问题