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

如何在MongoDB中获取指定搜索产品的全部分类?

问题描述

我当前使用以下MongoDB查询:

db.test_products.find(
{ $text: { $search: 'Iphone 6' } },
{ score: { $meta: "textScore" } })
.sort({ score:{$meta: "textScore"} })
.limit(20)

该查询返回前20个产品,但实际匹配结果超过20条。我希望获取该搜索词对应的所有分类,以便在UI上展示搜索产品的全部分类,期望输出格式如下:

{
    products: [{1...20}],
    categories: [
        "Mobile Phones",
        "Cellphones & Telecommunications/Phone Bags & Cases/Wallet Cases",
        "Cellphones & Telecommunications/Mobile Phone Parts/Mobile Phone Motherboards",
        "Cellphones & Telecommunications/Mobile Phone Parts/Mobile Phone LCD Screens",
        "...",
    ]
}

我确定MongoDB可以实现该查询,但目前不知如何编写。

注:我当前为title字段创建了text索引,不确定使用Realm的search索引实现自动补全是否会有较大差异。


解决方案

方法1:聚合管道$facet阶段(推荐单请求实现)

利用$facet可以在一次聚合操作中同时执行多个独立的处理分支,刚好满足同时获取分页产品和全部分类的需求:

db.test_products.aggregate([
  // 过滤所有匹配文本搜索的文档
  { $match: { $text: { $search: 'Iphone 6' } } },
  // 添加文本匹配分数字段,用于排序
  { $addFields: { score: { $meta: "textScore" } } },
  // 分两个分支处理数据
  {
    $facet: {
      // 分支1:获取排序后的前20个产品
      products: [
        { $sort: { score: { $meta: "textScore" } } },
        { $limit: 20 }
      ],
      // 分支2:去重并整理所有分类
      categories: [
        { $group: { _id: "$category" } },
        { $sort: { _id: 1 } },
        { $project: { _id: 0, category: "$_id" } },
        { $group: { _id: null, list: { $push: "$category" } } },
        { $project: { _id: 0, categories: "$list" } }
      ]
    }
  },
  // 展开分类结果数组
  { $unwind: "$categories" },
  // 整理为期望的输出结构
  { $project: { products: 1, categories: "$categories.categories" } }
])

关键逻辑说明:

  • $match阶段筛选所有符合文本搜索条件的文档;
  • $addFields添加匹配分数,保证产品排序逻辑和原查询一致;
  • $facet的products分支完成排序和分页,返回前20条结果;
  • $facet的categories分支通过$group去重分类,再整理为数组格式;
  • 最后通过$unwind和$project将结果整合为你需要的结构。

方法2:两次独立查询(简单直观)

如果不想使用聚合管道,也可以发起两次查询后手动组合结果:

  1. 获取前20个产品:
const products = db.test_products.find(
  { $text: { $search: 'Iphone 6' } },
  { score: { $meta: "textScore" } }
).sort({ score: { $meta: "textScore" } }).limit(20).toArray();
  1. 获取所有去重的分类:
const categories = db.test_products.distinct("category", { $text: { $search: 'Iphone 6' } });
  1. 组合结果:
const result = { products, categories };

说明:

这种方式逻辑简单,但会发起两次数据库请求,数据量较大时性能略低于单请求聚合方案。


关于Realm Search索引的差异说明

Realm的Search索引(基于MongoDB Atlas Search)和原生text索引的核心差异:

  • 功能范围:Atlas Search支持自动补全、模糊搜索、自定义分词等复杂场景,原生text索引仅支持基础文本匹配;
  • 语法差异:Atlas Search使用$search操作符,语法和原生$text完全不同;
  • 性能表现:大规模数据集下,Atlas Search的搜索性能更优,且支持更多优化配置;
  • 自动补全实现:原生text索引无法直接实现自动补全,Atlas Search的autocomplete类型索引是更合适的选择。

若切换为Atlas Search,对应的聚合查询示例(需提前创建Search索引):

db.test_products.aggregate([
  {
    $search: {
      text: {
        query: "Iphone 6",
        path: "title"
      }
    }
  },
  { $addFields: { score: { $meta: "searchScore" } } },
  {
    $facet: {
      products: [
        { $sort: { score: -1 } },
        { $limit: 20 }
      ],
      categories: [
        { $group: { _id: "$category" } },
        { $sort: { _id: 1 } },
        { $project: { _id: 0, category: "$_id" } },
        { $group: { _id: null, list: { $push: "$category" } } },
        { $project: { _id: 0, categories: "$list" } }
      ]
    }
  },
  { $unwind: "$categories" },
  { $project: { products: 1, categories: "$categories.categories" } }
])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 08:31:04