skip to Main Content

im creating a project where Im using mongoDB and I want to query some recipes.

example of recipe document in my db
I want to get recipes where "ingredients" array (sentences), have any words inside matching another array (single words).

I came up with something like this:

const recipes = await recipe
.aggregate([
  
  // add a weight parameter based of number of ingredients matching searched ingredient
  {
    $project: {
      name: 1,
      ingredients: 1,
      tags: 1,
      url: 1,
      weight: {
        $add: [
          {
            $size: {
              $setIntersection: ["$ingredients", ingrArr],
            },
          },
        ],
      },
    },
  },
  { $sort: { weight: -1 } },
])

It shows recipes where there are exact strings like "flour" and I added "weight" to sort them based on number of matching words, however it would not show something like: "cup of flour".

I tried $unwind, but i couldn’t make it work.
could anybody help me?

2

Answers


  1. Chosen as BEST ANSWER

    I had to add regular expression array and include it in query. This happens to work like I wanted. thanks

    let findString = "";
    ingrArr.forEach((e, index) => {
    index !== ingrArr.length - 1 ? (findString += e + "|") : (findString += e);
    });
    console.log(findString);
    const recipes = await recipe
    .aggregate([
      // add a weight parameter based of number of ingredients matching searched 
    ingredient
      {
        $addFields: {
          weight: {
            $size: {
              $filter: {
                input: "$ingredients",
                as: "element",
                cond: {
                  $regexMatch: {
                    input: "$$element",
                    regex: RegExp(`${findString}`),
                  },
                },
              },
            },
          },
        },
      },
      { $sort: { weight: -1 } },
    

  2. document

    {
            name: "A Simple Seafood Bisque",
            ingredients: [
                "1 (12 ounce) can evaporated milk",
                "1/2 cup half-and-half",
                "1/2 cup dry white wine",
                "1 roasted red pepper, chopped",
                "2 teaspoons butter",
                "1 bay leaf",
                "1 pinch salt",
                "1 dash hot pepper sauce (such as Tabasco's)",
                "2 (8 ounce) cans oysters, drained and rinsed",
                "2 (6.5 ounce) cans chopped clams with juice",
                "1 cup chopped portobello mushrooms",
                "2 green onions, minced"
            ],
            url: "http://allrecipes.com/recipe/77790/a-simple-seafood-bisque/"
    
        }
    

    query

    const key = 'pepper'
        
    db.collection.aggregate(
        {
            $match: {}
        },
        {
            $addFields: {
                weight: {
                    $size: {
                        $filter: {
                            input: '$ingredients',
                            as: 'element',
                            cond: {
                                $regexMatch: { input: '$$element', regex: RegExp(key) }
                            }
                        }
                    }
                }
    
            }
    
        }
    )
    

    the result added a field weight with number of matched element

    "weight" : 2
    

    or easier way to use $text and $search by create text index at ingredients field and query

    db.collection.find( 
        { $text: { $search: "pepper" } },{ score: { $meta: "textScore" } }
       
    )
    

    the result added a filed score of search

    "score" : 1.1833333333333333
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search