Home > Net >  Perform full search (using `$regex`) on several fields if search term is presented using aggregation
Perform full search (using `$regex`) on several fields if search term is presented using aggregation

Time:08-15

I have a service that displays products. I need to be able to search products by their fields (product name, barcode or sku).

Previously I used this approach

const query: FilterQuery<TProductSchema> = {};

if (search) {
  query.$or = [
    {
      productName: {
        $regex: String(search).split(' ').join('|'),
        $options: 'i',
      },
    },
    {
      barcode: {
        $regex: String(search),
        $options: 'i',
      },
    },
    { sku: { $regex: String(search).split(' ').join('|'), $options: 'i' } },
  ];
}

if (folderId && folderId !== 'all') {
  query.folder = { _id: folderId };
}

const products = await ProductModel.find<HydratedDocument<TProductSchema>>(query)
  .limit(Number(limit) === -1 ? 0 : Number(limit))
  .skip(Number(page) * Number(limit));

and it worked well but now I also need to include all documents count (which changes depending on selected folderId) in the resulting object.

I thought I could do it with the aggregation framework but I can't figure out how to conditionally match documents only if search is presented.

I thought I could do something like that

const products = await ProductModel.aggregate([
  { $match: {/* match folder */ },
  { /* count matched documents */ },
  // next search documents IF `search` is present
  {
    $match: {
      $cond: [search, /* here goes `query` object, '']
    }
  },
]);

but it doesn't work saying unknown top level operator "$cond"

So how can I apply $match conditionally?

CodePudding user response:

You have created query in first code and you need to pass same in $match it should work same.

$match: query
  • Related