$match没有匹配所输入的所有字段

后端开发 2026-07-12

我在处理一个使用 $lookup 运算符的MongoDB聚合管道时遇到了问题。目标是创建一个管道,根据输入字段过滤数据库中的数据,并使用 $lookup 返回匹配的数据。

然而,当我请求特定字段时,结果始终是null。我怀疑我的管道逻辑可能有问题,想寻求帮助来识别并解决它。

export const bookIssuedFind = async (req: Request, res: Response) => {
  try {
    const searchTerm = req.body || {};
    const filter:issued = {};

    if (searchTerm.issuer_id) filter.issuer_id = searchTerm.issuer_id;
    if (searchTerm.user_id) filter.user_id = searchTerm.user_id;
    if (searchTerm.issue_date) filter.issue_date = searchTerm.issue_date;
    if (searchTerm.return_date) filter.return_date = searchTerm.return_date;
    if (searchTerm.book_status) filter.book_status = searchTerm.book_status;
    if (searchTerm.book_id) filter.book_id = searchTerm.book_id;

    const pipeline = [];

    if (Object.keys(filter).length > 0) {
      pipeline.push({ $match: filter });
    }
    console.log(pipeline)
    pipeline.push(
      {
        $lookup: {
          from: "users",
          localField: "issuer_id",
          foreignField: "_id",
          as: "IssuerDetails"
        }
      },
      {
        $lookup: {
          from: "users",
          localField: "user_id",
          foreignField: "_id",
          as: "UserDetails"
        }
      },
      {
        $lookup: {
          from: "books",
          localField: "book_id",
          foreignField: "_id",
          as: "BookDetails"
        }
      }
      // { $unwind: { path: '$IssuerDetails', preserveNullAndEmptyArrays: true } },
      // { $unwind: { path: '$UserDetails', preserveNullAndEmptyArrays: true } },
      // { $unwind: { path: '$BookDetails', preserveNullAndEmptyArrays: true } },
    );
    console.log(pipeline)
    const issued = await Book_issueed.aggregate(pipeline).exec();
    console.log(issued)
    const result = (Object.keys(filter).length > 0) ? (issued[0] || null) : issued;
    return res.status(200).json(result);
  } catch (error) {
    if (error instanceof Error) {
      res.status(500).json({ message: `${error.message}` });
    }
  }
}

我得到的输出是:

[ { '$match': { issuer_id: '69a6810495126821c9e08281' } } ]
[
  { '$match': { issuer_id: '69a6810495126821c9e08281' } },
  {
    '$lookup': {
      from: 'users',
      localField: 'issuer_id',
      foreignField: '_id',
      as: 'IssuerDetails'
    }
  },
  {
    '$lookup': {
      from: 'users',
      localField: 'user_id',
      foreignField: '_id',
      as: 'UserDetails'
    }
  },
  {
    '$lookup': {
      from: 'books',
      localField: 'book_id',
      foreignField: '_id',
      as: 'BookDetails'
    }
  }
]
[]
[ { '$match': { issuer_id: '69a6810495126821c9e08281' } } ]
[
  { '$match': { issuer_id: '69a6810495126821c9e08281' } },
  {
    '$lookup': {
      from: 'users',
      localField: 'issuer_id',
      foreignField: '_id',
      as: 'IssuerDetails'
    }
  },
  {
    '$lookup': {
      from: 'users',
      localField: 'user_id',
      foreignField: '_id',
      as: 'UserDetails'
    }
  },
  {
    '$lookup': {
      from: 'books',
      localField: 'book_id',
      foreignField: '_id',
      as: 'BookDetails'
    }
  }
]
[]
import { Document, Model, model, Schema } from "mongoose";

interface IUser {
  name: string;
  mobileno: string;
  email: string;
  role: "Librarian" | "Local" | "Student";
  password: string;
  repeat_password?: string | null;
}

interface IUserDocument extends IUser, Document {}

const UserSchema = new Schema<IUserDocument>({
      name: {
        type: String,
        required: true, 
        trim: true,
    },
    mobileno: {
        type: String,
        unique: true,
        required: true,
        match: /^[0-9]{10}$/,
    },
    email: {
        type: String,
        unique: true,
        required: true,
        lowercase: true,
        match: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
    },
    role: {
        type: String,
        enum: ['Librarian', 'Local', 'Student'],
        required: true
    },
    password: {
        type: String,
        match: /[0-9a-zA-Z]*\d[0-9a-zA-Z]*/,
        required: true
    },
    repeat_password: { type: String, ref: 'password' }
});

export const User: Model<IUserDocument> = model<IUserDocument>("User", UserSchema);
import mongoose from "mongoose";
const { Schema } = mongoose

export const books = new Schema({
    book_name: { type: String, minLength: 3, maxLength: 30, required: true },
    quantity: { type: Number, maxLength: 30, required: true },
    description: { type: String, maxLength: 200 },
    author: { type: String, minLength: 3, maxLength: 30, required: true },
    category: { type: String, required: true },
    shelf_name: { type: String, minLength: 3, maxLength: 30, required: true },
});

export const Books = mongoose.model('Books', books);

解决方案

我已经解决了这个问题,以下是我的解决方案:我在管道中实现了一个表达式来匹配字段。为此,我使用了 $expr$and 运算符。

    if (Object.keys(filter).length > 0) {
      pipeline.push({ $match: { $expr: { $and: filter } } });
    }
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章