Anyone tried mongodb.com's Atlas Search?

For multi-tenant could you not use Search itself to filter the result to only specific tenants? So something like:

tenantId : {
must_be: [1, 2, 3]
}

Is there a reason that wouldn’t work? I’m just going by the references on: https://docs.atlas.mongodb.com/reference/atlas-search/performance#-match-aggregation-stage-usage.

I’m not sure whether I understand your idea. Of course, you can use $match right after $search, but this will search for all matches (across all tenants) and later filter them. Now, while this may work, it will scale as the $search alone, not the $match + $search ($match for tenant ID may get rid of 99.9% results (if there is 1000 tenants of similar size).

Also, must itself is not an operator - it’s just part of the compound operator. That means you’d still have to use equals, which works only for booleans and ObjectIds.

So the way I’m doing this for a multi-tenant app is to use a compound query:

await Collection.rawCollection().aggregate(
  [
				{
					$search: {
						compound: {
							filter: [{
							text: {
								query: this.userId,
								path: 'createdBy',
								},
							}],
							must: [{
									text: {
										query,
										path,
										fuzzy: {
											maxEdits: 2,
											prefixLength: 1,
										},
									},
							}],
						},
					},
				},
				{
					$project: {
						score: { $meta: 'searchScore' },
						createdAt: 1,
					},
				},
			]
).toArray();

Where the ‘createdBy’ path is indexed using lucene.keyword so that it requires an exact match. All my tests indicated that this is accurate and doesn’t pollute results and this was confirmed by a member of the Atlas Search team.

That said, I want to subscribe to the results so I have an added check whereby the search operation only brings up the relevant _ids and I then subscribe to those _ids and ensure that the match confirms that the createdBy matches the subscribing userId.

Hope that makes sense.

1 Like