首页 > 解决方案 > 如何从数据库中过滤食谱?

问题描述

我有一个食谱集合,看起来像这样:

{
  "Name": "Omelet",
  "Ingredients": ["Eggs", "Milk", "Butter"]
},
{
  "Name": "Pancakes",
  "Ingredients": ["Eggs", "Milk", "Butter", "Flour", "Sugar", "Salt"]
},
{
  "Name": "Random recipe",
  "Ingredients": ["Eggs", "Milk"]
}

我正在尝试获取包含完全包含在查询中的成分的食谱。例如,如果我有查询鸡蛋、牛奶和黄油,那么我必须从上面的集合中获取煎蛋卷和“随机食谱”,而不是煎饼,因为我没有另外 3 种必要的成分。如果我只有鸡蛋和牛奶,那么它必须只返回“随机食谱”。换句话说,我只想要可以用现有原料制作的食谱。我搜索了文档,但找不到确切的实现方式。有任何想法吗?我正在使用 Golang 作为我的后端,所以如果你在上面写一个例子会更好。如果有任何帮助,我将不胜感激。

现在我写了这个函数,它返回所有带有某些成分的食谱,但这没有考虑到缺少的成分和不需要所有转移成分的食谱:

func GetTestRecipesFromDB(ingredients []string) *[]Recipe {
    collection := client.Database("food_db").Collection("recipes")

    ctx, _ := context.WithTimeout(context.Background(), 10 * time.Second)

    var recipes []Recipe
    var cursor *mongo.Cursor

    cursor, err := collection.Find(ctx, bson.D{
        {"Ingredients", bson.D{{"$all", ingredients}}},
    })

    if err != nil {
        log.Fatal(err)
        return nil
    }

    if err = cursor.All(ctx, &recipes); err != nil {
        log.Fatal(err)
        return nil
    }

    return &recipes
}

编辑:根据这个答案(谢谢@MontgomeryWatts 的建议)我在Go中写了这个并且它有效:

    query := bson.M{
        "$match" : bson.M{
            "$expr" : bson.M{
                "$setIsSubset": []interface{}{
                    "$Ingredients",
                    ingredients,
                },
            },
        },
    }

    cursor, err := collection.Aggregate(ctx, []bson.M{query})
    if err != nil {
        log.Fatal(err)
        return nil
    }

感谢大家的帮助!

标签: arraysdatabasemongodbgomongodb-query

解决方案


您可以通过使用$filter的聚合管道来完成此操作

  • $match 以便您只考虑具有至少一种匹配成分的食谱
  • $addFields 使用 $filter 创建OtherIngredient字段以消除查询的成分数组Ingredients
  • $match 只选择没有其他成分的食谱
  • $project 删除临时字段
[
  {$match: {Ingredients: {
        $in: ["Eggs","Milk","Butter"]
  }}},
  { $addFields: {
      OtherIngredient: {
        $filter: {
          input: "$Ingredients",
          cond: {$not: {$in: [
                "$$this",
                ["Eggs","Milk","Butter"]
          ]}}
        }
      }
  }},
  {$match: {"OtherIngredient": []}},
  {$project: {OtherIngredient: 0}}
])

操场


推荐阅读