Hi, I’m in the process of migrating the search in an application from Elastic to MongoDB Atlas, and the results have been good.
I’m now attempting to replicate some of the features I’ve been using in Elastic, such as the analyzers:
{
"analyzer": "lucene.standard",
"searchAnalyzer": "lucene.standard",
"mappings": {
"dynamic": false,
"fields": {
"attributes": {
"dynamic": true,
"type": "document"
},
"createdAt": {
"type": "date"
},
"isActive": {
"type": "boolean"
},
"isFavourite": {
"type": "boolean"
},
"note": {
"analyzer": "htmlStrippingAnalyzer",
"type": "string"
},
"title": {
"multi": {
"keywordAnalyzer": {
"analyzer": "ngramShingler",
"type": "string"
}
},
"type": "string"
},
"typeOfAsset": {
"type": "string"
},
"updatedAt": {
"type": "date"
}
}
},
"analyzers": [
{
"charFilters": [],
"name": "ngramShingler",
"tokenFilters": [
{
"maxShingleSize": 3,
"minShingleSize": 2,
"type": "shingle"
}
],
"tokenizer": {
"maxGram": 5,
"minGram": 2,
"type": "nGram"
}
},
{
"charFilters": [
{
"ignoredTags": [
"a",
"div",
"p",
"strong",
"em",
"img",
"figure",
"figcaption",
"ol",
"ul",
"li",
"span"
],
"type": "htmlStrip"
}
],
"name": "htmlStrippingAnalyzer",
"tokenFilters": [],
"tokenizer": {
"type": "standard"
}
}
]
}
… and the code in Node is:
r
return new Promise( async (resolve, reject) => {
try {
const search = {
$search: {
index: 'assets',
compound: {
should: [{
text: {
query: args.phraseToSearch,
path: [{ value: 'title', multi: 'keywordAnalyzer' }],
score: { boost: { value: 3 } }
}
}, {
text: {
query: args.phraseToSearch,
path: 'note'
}
}]
}
}
}
const project = {
$project: {
_id: 0,
id: '$_id',
userId: 1,
folderId: 1,
title: 1,
note: 1,
typeOfAsset: 1,
isFavourite: 1,
createdAt: 1,
updatedAt: 1,
isActive: 1,
attributes: 1,
preferences: 1,
score: {
$meta: 'searchScore'
}
}
}
const match = {
$match: {
userId: args.userId
}
}
const skip = {
$skip: args.skip
}
const limit = {
$limit: args.first
}
const group = {
$group: {
_id: null,
count: { $sum: 1 }
}
}
const sort = {
$sort: {
[args.orderBy]: args.orderDirection === 'asc' ? 1 : -1
}
}
const searchAllAssets = await Models.Assets.schema.aggregate([
search, project, match, sort, skip, limit
])
const [ totalNumberOfAssets ] = await Models.Assets.schema.aggregate([
search, project, sort, match, group
])
return await resolve({
searchAllAssets: searchAllAssets,
totalNumberOfAssets: totalNumberOfAssets.count
})
} catch (exception) {
return reject(new Error(exception))
}
})
When I use the search I get the following error:
[GraphQL error]: Message: MongoServerError: PlanExecutor error during aggregation :: caused by :: Remote error from mongot :: caused by :: query has expanded into too many sub-queries internally: maxClauseCount is set to 1024
I’ve Googled maxClauseCount
but found nothing useful.
I don’t have a lot of experience debugging queries (I’m using the Compass client, and make occasional use of MONGOSH), and it’s possible I’ve got something wrong with the index (I’ve copied and pasted the two analyzers from the documentation and then made a few tweaks).
Any advice would be much appreciated.