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?
CodePudding user response:
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
CodePudding user response:
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 } },