0

I have to implement search using search indexes in MongoDB Atlas as well as normal browse feature. This includes filtering, match, sort, skip, limit (pagination). I have made an aggregation pipeline to achieve all this. First I push the search query to my pipeline, then match, then sort, then skip and finally the limit query.

Here's how it goes:

query = [];
query.push({
    $search: {
      index: 'default'
      text: {
        query: searchQuery
        path: {  }
      }
    }
  });
 query.push({
      $sort: sort,
    });
 query.push({
    $match: {
      type: match
    },

query.push({
  $skip: skip
});
query.push({
  $limit: perPage
});

let documents = await collection.aggregate(query);

The results I get so far are correct. However, for pagination, I also want to get the total count of documents. The count must take the "match" and "searchQuery" (if any) take into account. I have tried $facet but it gives error $_internalSearchMongotRemote is not allowed to be used within a $facet stage

SunAns
  • 193
  • 1
  • 2
  • 15

1 Answers1

1

So, I see a few challenges with this query.

  1. The $sort stage may not be needed. All search queries are sorted by relevance score by default. If you need to sort on some other criterion, then it may be appropriate.

  2. The $match stage is probably not needed. What most people are looking for when they are trying to match is a compound filter. As you can see from the docs, a filter behaves like a $match in ordinary MongoDB. From where I am, your query should probably look something like:

If you would like a fast count of the documents returned, you need to use the new count operator. It is available on 4.4.11 and 5.0.4 clusters. You can read about it here.


query = [];
query.push({
    $search: {
      index: 'default'
      "compound": {
      "filter": [{
        "text": {
          "query": match,
          "path": type
        }
      }],
      "must": [{
        "text": {
          "query": searchQuery,
          "path": { }
        }
      }]
    }, 
     "count": {
      "type": "total"
     }
   }
  });

query.push({
  $skip: skip
});

query.push({
  $limit: perPage
});

/* let's you use the count, can obviously project more fields */
query.push({
  $project: "$$SEARCH_META"
});

let documents = await collection.aggregate(query);



  [1]: https://docs.atlas.mongodb.com/reference/atlas-search/compound/#mongodb-data-filter
  [2]: https://docs.atlas.mongodb.com/reference/atlas-search/counting/#std-label-count-ref
Nice-Guy
  • 1,457
  • 11
  • 20
  • Hey thanks, I know I'm late but I'm here again. How to use that 'count'? I want the count to show in my output. By count I mean the total number of documents that matches with the searchQuery. – SunAns Oct 03 '22 at 21:21
  • It's a fair question and I should update my answer. You need to project `$$SEARCH_META` Thanks for the question – Nice-Guy Oct 06 '22 at 02:25