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

Node.js下MongoDB关联双集合实现记者姓名与报道内容多条件搜索

Node.js + MongoDB 跨集合搜索实现方案

核心逻辑

通过联表查询关联记者和报道两个集合,同时匹配记者姓名、报道标题、报道描述三个维度的关键词,返回符合条件的报道信息。

代码实现(基于Mongoose,最常用的MongoDB Node.js工具库)

1. 定义数据模型

// 引入依赖
const mongoose = require('mongoose');

// 记者集合模型
const journalistSchema = new mongoose.Schema({
  journalist_FirstName: String,
  journalist_LastName: String,
  // 其他自定义字段
});
const Journalist = mongoose.model('Journalist', journalistSchema);

// 报道集合模型
const storySchema = new mongoose.Schema({
  journalistId: { type: mongoose.Schema.Types.ObjectId, ref: 'Journalist' },
  storyTitle: String,
  briefDescription: String,
  publishDate: Date,
  // 其他自定义字段
});
const Story = mongoose.model('Story', storySchema);

2. 核心搜索逻辑

async function searchStories(keyword) {
  // 构造不区分大小写的正则匹配规则
  const searchRegex = new RegExp(keyword, 'i');
  
  // 调用聚合管道一次性完成联表+匹配+字段筛选
  const result = await Story.aggregate([
    // 关联记者集合,拿到对应记者的姓名信息
    {
      $lookup: {
        from: 'journalists', // 此处为MongoDB中记者集合的实际名称,默认是模型名小写复数
        localField: 'journalistId',
        foreignField: '_id',
        as: 'journalist'
      }
    },
    // 将关联返回的数组格式转为单个对象
    { $unwind: '$journalist' },
    // 匹配所有符合关键词的记录
    {
      $match: {
        $or: [
          { 'journalist.journalist_FirstName': searchRegex },
          { 'journalist.journalist_LastName': searchRegex },
          { storyTitle: searchRegex },
          { briefDescription: searchRegex }
        ]
      }
    },
    // 只返回需要的字段,可按需调整
    {
      $project: {
        storyTitle: 1,
        briefDescription: 1,
        publishDate: 1,
        _id: 0
      }
    }
  ]);

  // 格式化日期为示例要求的格式
  return result.map(item => ({
    storyTitle: item.storyTitle,
    briefDescription: item.briefDescription,
    publishDate: new Intl.DateTimeFormat('zh-CN', {
      year: 'numeric',
      month: 'long',
      day: 'numeric'
    }).format(item.publishDate)
  }));
}

3. 调用示例

// 用户输入关键词Kabita时调用
searchStories('Kabita').then(res => {
  console.log(res);
  /* 输出示例:
  [
    {
      storyTitle: 'Joining of two tables',
      briefDescription: 'MongoDB joining of tables',
      publishDate: '2021年11月21日'
    }
  ]
  */
});

性能优化建议

如果数据量较大,建议给搜索字段建立文本索引替代正则查询,性能提升明显:

// 给记者姓名字段建文本索引
await Journalist.collection.createIndex({
  journalist_FirstName: 'text',
  journalist_LastName: 'text'
});
// 给报道标题、描述字段建文本索引
await Story.collection.createIndex({
  storyTitle: 'text',
  briefDescription: 'text'
});

简化版实现(两次查询,写法更易懂)

如果不想写聚合管道,也可以分两次查询实现,小数据量下性能差异不大:

async function searchStoriesSimple(keyword) {
  const searchRegex = new RegExp(keyword, 'i');
  // 第一步:查询所有姓名匹配关键词的记者ID
  const matchJournalistIds = (await Journalist.find({
    $or: [
      { journalist_FirstName: searchRegex },
      { journalist_LastName: searchRegex }
    ]
  }, { _id: 1 })).map(item => item._id);

  // 第二步:查询符合条件的报道
  const stories = await Story.find({
    $or: [
      { journalistId: { $in: matchJournalistIds } },
      { storyTitle: searchRegex },
      { briefDescription: searchRegex }
    ]
  }, { storyTitle: 1, briefDescription: 1, publishDate: 1, _id: 0 });

  // 日期格式化逻辑同上
  return stories.map(item => ({
    ...item,
    publishDate: new Intl.DateTimeFormat('zh-CN', {
      year: 'numeric',
      month: 'long',
      day: 'numeric'
    }).format(item.publishDate)
  }));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 07:36:04