epilef
epilef

Reputation: 63

MongoDB aggregation $match with $or

Is there a way to search a mongodb database using an array of objects as search arguments?

Lets say I have the following search preferences:

preferences = [{
    product: "PRODUCT_A",
    minqty: 5,
    maxqty: 50
  },
  {
    product: "PRODUCT_B",
    minqty: 100,
    maxqty: 500
  }
]

In my database I have Jobs with the following structure:

{
  jobName: "job name",
  items: [{
      product: "PRODUCT_A"
      qty: 25
    },
    {
      product: "PRODUCT_F"
      qty: 300
    }

  ]
}

I would like to query the database using preferences and returning any jobs that match at least one of the criteria's.

ATTEMPT 1:

I managed to use all my preferences as filters, but $match is cumulative, the way it's written it works like && in javascript. My goal is to have "match THIS || match THAT".

let pipeline = [];

preferences.map((item) => {
  let search = {
    product: item.product,
    quantity: { $gte: item.minqty, $lte: item.maxqty },
  };

  return pipeline.push({
    $match: {
      items: {
        $elemMatch: search,
      },
    },
  });
});

const jobs = await Job.aggregate(pipeline);

ATTEMPS 2 (SUCCESS):

let search = [];

preferences.map((item, index) => {
  let arguments = {
    product: item.product,
    quantity: { $gte: item.minqty, $lte: item.maxqty },
  };

  search.push(arguments);
});

let pipeline = [
  {
    $match: {
      items: {
        $elemMatch: {
          $or: search,
        },
      },
    },
  },
];

const jobs = await Job.aggregate(pipeline);

Upvotes: 0

Views: 1855

Answers (1)

HM Nayem
HM Nayem

Reputation: 2437

I think you can create your search object by reducing the preferences array and use the $or operator. When you map the preferences array it is returning an array that will perform and operation. you need an object like -

{
  $or: [{product1, quantity1}, {product2, quantity2}]
}

I guess you got my point.

Upvotes: 1

Related Questions