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

MongoDB查询:如何筛选可用现有食材制作的所有食谱

解决食谱匹配的MongoDB查询问题

你需要的是找出所有食材种类都被手头食材覆盖的食谱,而非恰好仅包含指定食材的食谱。原查询的问题在于用$size限制了食材数量,且$all的逻辑方向不对——它只确保手头食材都在食谱里,而非食谱食材都在手头里。

推荐方案:用$expr + $setIsSubset

MongoDB的$setIsSubset操作符可以直接判断一个集合是否是另一个集合的子集,完美匹配你的需求。假设手头食材数组为['banana', 'milk', 'apple'],查询语句如下:

db.recipes.find({
  $expr: {
    $setIsSubset: [
      "$ingredients.name", // 自动提取当前食谱的所有食材名称组成数组
      ["banana", "milk", "apple"] // 你的手头食材列表
    ]
  }
})

这个查询会返回所有满足「食谱的每一种食材都在手头食材中」的文档,不管你手头多了多少额外食材,也不管食谱本身有几种食材。

替代方案:反向排除不匹配的食谱

通过$not和$elemMatch,排除那些包含手头没有的食材的食谱:

db.recipes.find({
  "ingredients.name": {
    $not: {
      $elemMatch: {
        $nin: ["banana", "milk", "apple"]
      }
    }
  }
})

逻辑是:食谱中不存在任何一种食材,其名称不在手头食材列表里——等同于所有食材都符合要求。

原查询的问题分析

  • $all:['banana', 'milk']仅确保食谱同时包含这两种食材,但无法阻止食谱包含其他你没有的食材(比如橙子),会返回不符合要求的结果。
  • ingredients: {$size:2}强制要求食谱恰好有2种食材,会过滤掉食材更少的有效食谱(比如仅需香蕉的食谱),也不符合需求。

扩展:考虑食材数量匹配

如果需要校验食材数量(比如手头香蕉数量≥食谱所需),可以在查询中加入数量条件:

db.recipes.find({
  $expr: {
    $setIsSubset: ["$ingredients.name", ["banana", "milk", "apple"]]
  },
  "ingredients": {$elemMatch: {name: "banana", qty: {$lte: 3}}},
  "ingredients": {$elemMatch: {name: "milk", qty: {$lte: 2}}}
})

这里假设你手头有3个香蕉、2杯牛奶,会筛选出数量符合要求的食谱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 20:33:22