You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mongoose findOne中$and查询失效,如何仅返回status:false的嵌套文档?

问题描述

我定义了如下Mongoose Schema:

const borrowBookSchema = new mongoose.Schema({
    member_id  : {
        type : String,
        required: true,
    },
    member_name : {
       type : String,
       required : true
    },
    bookdetails : [{
        bookid : String,
        bookname : String,
        todaydate : String,
        returndate : String,
        status : Boolean
    }]
})

我希望查询仅返回bookdetails数组中status: false的元素,但使用以下代码查询时,结果同时返回了status: true的元素:

const returnBorrowBook = (req,res) => {
  const {memberid} = req.body
  let response =  await BorrowBook.findOne({$and : [{member_id : memberid} ,{"bookdetails.status" : false}]})
  console.log(response)
}

返回结果示例:

bookdetails: [
    {
      bookid: '63f5d00a0effd7323ac20bea',
      bookname: 'Atomic Habits',
      todaydate: '03/03/2023',
      returndate: '03/03/2023',
      status: true,
      _id: new ObjectId("64016a278023cdb8a881a35a")
    },
    {
      bookid: '63f5d00a0effd7323ac20bea',
      bookname: 'Atomic Habits',
      todaydate: '01/03/2023',
      returndate: null,
      status: false,
      _id: new ObjectId("64016b365203f7c11528392e")
    }
  ]
原因分析

原查询中的{"bookdetails.status": false}仅用于筛选文档(即找到包含至少一个status: false的bookdetails项的文档),而非过滤数组内的元素。因此返回的是完整文档,包含所有bookdetails元素。

解决方案

方法1:使用聚合管道(Aggregation Pipeline)

通过$match筛选目标文档,再用$project配合$filter过滤数组元素:

const returnBorrowBook = async (req, res) => {
  const { memberid } = req.body;

  const [result] = await BorrowBook.aggregate([
    // 筛选符合条件的文档
    { $match: { member_id: memberid, "bookdetails.status": false } },
    // 过滤bookdetails数组,仅保留status为false的元素
    {
      $project: {
        member_id: 1,
        member_name: 1,
        bookdetails: {
          $filter: {
            input: "$bookdetails",
            cond: { $eq: ["$$this.status", false] }
          }
        }
      }
    }
  ]);

  console.log(result);
  res.send(result || null);
};

方法2:使用findOne配合投影过滤

直接在findOne的投影参数中使用$filter:

const returnBorrowBook = async (req, res) => {
  const { memberid } = req.body;

  const result = await BorrowBook.findOne(
    { member_id: memberid, "bookdetails.status": false },
    {
      member_id: 1,
      member_name: 1,
      bookdetails: {
        $filter: {
          input: "$bookdetails",
          cond: { $eq: ["$$this.status", false] }
        }
      }
    }
  );

  console.log(result);
  res.send(result);
};

额外提示

原查询中的$and是多余的,MongoDB查询条件默认是逻辑与关系,可简化为{ member_id: memberid, "bookdetails.status": false }。


内容的提问来源于stack exchange,提问作者safwanpaloli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 00:13:33