'Full text Search returns empty array using mongoose and Node.js
None of the other SO articles got me a solution.
Schema Definition:
const jobSchema = new (require("mongoose").Schema)(
{
userID: { type: require("mongoose").Schema.Types.ObjectId, ref: "User" },
emailID: { type: String, trim: true, required: false },
jobTitle: { type: String, trim: true, required: false },
jobDescription: { type: String, trim: true, required: false },
company: { type: String, required: false },
position: { type: String, required: false },
noOfYearsExperience: { type: String, required: false },
domain: { type: String, required: false },
link: { type: String, required: false },
location: { type: String, required: false },
jobCreationStatus: { type: String, required: false },
isActive: { type: Boolean, default: true, required: false },
isFeatured: { type: Boolean, default: false, required: false },
ttl: { type: String, required: false },
expiryDate: { type: Date, required: false },
expired: { type: Boolean, default: false, required: false },
applicants: [{ userId: { type: require("mongoose").Schema.Types.ObjectId, ref: "User" } }],
},
{
timestamps: true,
}
);
jobSchema.index({ jobTitle: "text", domain: "text", location: "text" }, { weights: { jobTitle: 3, domain: 2, location: 1 } });
Query Function:
module.exports.getJobs = async (filters, searchText, pageNo, isAuth) => {
try {
if (!filters["expired"]) filters["expired"] = false;
if (!searchText) searchText = null;
return await Job.aggregate([
// { $match: { $or: [filters, { $text: { $search: "Kolkata" } }] } },
{ $match: { $text: { $search: "Kolkata" } } },
{
$facet: {
metadata: [{ $count: "total" }, { $addFields: { page: pageNo } }],
data: [{ $skip: pageNo * 30 }, { $limit: 30 }],
},
},
]);
} catch (err) {
console.log(err);
}
};
The exact behavior I want:
If searchText is null, match the filters. Else, just return the documents that match the searchText on the indexed fields. "Kolkata" is to be replaced by searchText.
The problem:
If the given $match are removed from the aggregate above, the query works fine. Response in Postman:
{
"status": "success",
"message": [
{
"metadata": [
{
"total": 1,
"page": 0
}
],
"data": [
{
"_id": "620aa56f5966e4052229232c",
"emailID": "[email protected]",
"company": "SpaceShift",
"noOfYearsExperience": "4",
"domain": "Angulaar, React",
"location": "Kolkata",
"jobCreationStatus": "job",
"isActive": true,
"ttl": "2 week",
"expired": false,
"createdAt": "2022-02-14T18:54:39.275Z",
"updatedAt": "2022-02-14T18:54:39.275Z",
"__v": 0,
"jobTitle": "Frontend Developer"
}
]
}
]
}
Using { $match: { $text: { $search: "Kolkata" } } } returns:
{
"status": "success",
"message": [
{
"metadata": [],
"data": []
}
]
}
Using { $match: { $or: [filters, { $text: { $search: "Kolkata" } }] } } returns:
MongoServerError: error processing query: ns=job-database.jobsTree: $or
expired $eq false
TEXT : query=Kolkata, language=english, caseSensitive=0, diacriticSensitive=0, tag=NULL
Sort: {}
Proj: {}
Collation: { locale: "simple" }
planner returned error :: caused by :: Failed to produce a solution for TEXT under OR - other non-TEXT clauses under OR have to be indexed as well.
at MessageStream.messageHandler (/home/deep/Personal/job-qna/node_modules/mongoose/node_modules/mongodb/lib/cmap/connection.js:467:30)
at MessageStream.emit (events.js:375:28)
at processIncomingData (/home/deep/Personal/job-qna/node_modules/mongoose/node_modules/mongodb/lib/cmap/message_stream.js:108:16)
at MessageStream._write (/home/deep/Personal/job-qna/node_modules/mongoose/node_modules/mongodb/lib/cmap/message_stream.js:28:9)
at writeOrBuffer (internal/streams/writable.js:358:12)
at MessageStream.Writable.write (internal/streams/writable.js:303:10)
at TLSSocket.ondata (internal/streams/readable.js:726:22)
at TLSSocket.emit (events.js:375:28)
at addChunk (internal/streams/readable.js:290:12)
at readableAddChunk (internal/streams/readable.js:265:9) {
ok: 0,
code: 291,
codeName: 'NoQueryExecutionPlans',
'$clusterTime': {
clusterTime: new Timestamp({ t: 1645314629, i: 1 }),
signature: {
hash: new Binary(Buffer.from("0fa1bccca48bef06c203ef8c5a16857f5cdf16af", "hex"), 0),
keyId: new Long("7035651653462130689")
}
},
operationTime: new Timestamp({ t: 1645314629, i: 1 })
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
