I have subscriptions collection in the database, e.g:
[{
_id: new ObjectId(...),
query: {
size: { $in: [1, 2, 3] }
}
}, {
_id: new ObjectId(...),
query: {
name: { $eq: 'Shirt' },
}
}]
I need to find all subscriptions whose query matches the object. Is it possible? E.g:
Subscriptions.aggregate([{
$reverseMatch: {
size: 1,
name: 'Shirt',
},
}]);
2
Answers
This query effectively filters out subscriptions where the
size
field inside thequery
object matches any of the specified values (1, 2, or 3), thereby giving us the subscriptions that do not match the specified object. It’s a neat way to handle such filtering requirements in MongoDB aggregation pipelines.Assuming OP is asking about functionality similar to percolate query on ElasticSearch, it’s a design flaw, but rather a niche requirement.
The short answer is "NO" – there is no way to implement implement it with an arbitrary query stored in a document.
The problem lays in the separation between data and commands on protocol level. A json stored as a value remains
data
for life. There is no way to use it as a command / filter / query or any other control structure. Basically it’s fundamentally not possible to store a query / filter with native mongodb syntax in the database to run it against a document / collection on db side itself.What you can do:
implement own dsl similar to mongodb syntax
generally impossible task, but if you can limit query syntax to reasonable operations you can end up with something useful. An example below implements $eq and $in queries as in the OP. I didn’t test it thoughtfully, it’s there just to demonstrate scale of complexity of the approach.
And even for this approach the syntax for the "query" field in the subscription document should be adjusted to avoid
$
sign:implement matching engine in javascript
Using $function gives you much more flexibility. It would be easier to implement the matching engine there, but it comes with massive performance impact, and it will likely be disabled for security, so won’t go into details on this one. Just mentioning it as an option. Again, reaching 100% compatibility for arbitrary query is an enormous task, so you will need to put reasonable limitations on supported syntax.
implement on application level
If the subscription collection is reasonably small (like 1,000s to 10,000s of documents), you can load all documents to the serverside application, and run the queries in parallel. By default driver’s pull is 100 connections, which let you run 100 subscription queries at a time.
You will need to store the
document in a temporary collection, and run the subscription queries against it.