Given a reference array of strings: ["Comedy", "Horror", "Romance"]
,
I would like to query a Movie
model with this schema:
const MovieSchema = new Schema({ _id: { type: Types.ObjectId, required: true }, title: { type: String, required: true }, categories: [{ type: String }], });
Such that I will get results where I will get Movie
s with categories in common with the reference array, sorted by the amount of elements it has in common with the reference array. For example:
[ { _id: "57", title: "Sample Movie A", categories: ["Comedy", "Horror", "Romance", "Family"] }, { _id: "92", title: "Sample Movie B", categories: ["Comedy", "Romance", "Family", "Coming of Age"] } ]
Note that Movie A is the first in the results because it has 3 items in common with the reference array while Movie B only has 2 items in common.
How can I achieve this query using Mongoose 5.11.16?
Advertisement
Answer
You could use $setIntersection
to get a count of matching elements, add the resulting array-size as a new field to each document and and then sort by this field.
You could then extend the query to filter matches with a count greater than 0
and remove the categoryCount
from the output, e.g.
Movie.aggregate([ { "$addFields": { "categoryCount": { $size: { $setIntersection: [ [ "Comedy", "Horror", "Romance" ], "$categories" ] } } } }, { "$match": { categoryCount: { $gt: 0 } } }, { "$sort": { categoryCount: -1 } }, { "$project": { categoryCount: 0 } } ])
Example on mongoplayground: https://mongoplayground.net/p/ZlUNfB82FRK