Search code examples
mongodbmongoosemongodb-aggregation

Mongodb - how to use an aggregate text search with a find query


I'm using the aggregate method in Mongodb against a text search. I've tried various way with this and still can't find the correct way to filter my results. I've setup an index and it works fine with just the $text search and also works fine with just the query.

Here's my code to do a text search:

Model.aggregate([
    { $match: { $text: { $search: searchValue } } },
    { $project: { displayTitle: 1, title: 1, body: 1, _type: 1, _id: 1, score: { $meta: "textScore" } } },
    { $match: { score: { $gt: 1.0 } } }
], function (err, models) {

})

However I want to be able to filter the models further by this query:

Model.find({_parentIds: {$in: arrayOfIds}})

I would have thought that this would work:

Model.aggregate([
    { $match: { $text: { $search: searchValue }, _parentIds: {$in: arrayOfIds} } },
    { $project: { displayTitle: 1, title: 1, body: 1, _type: 1, _id: 1, score: { $meta: "textScore" } } },
    { $match: { score: { $gt: 1.0 } } }
])

But sadly it doesn't. Has anyone tried this or am I missing something?

Here's an example collection I'm searching through:

[{
    displayTitle: "first item",
    title: "first_item",
    _type: "item",
    _parentIds: ["123", "234"]
}, {
    displayTitle: "second item",
    title: "second_item",
    _type: "item",
    _parentIds: ["123", "234"]
}, {
    displayTitle: "third item",
    title: "third_item",
    _type: "item",
    _parentIds: ["345", "456"]
}]

My current search would be something like this:

searchValue = "item"
arrayOfIds = ["345"];

and would be expecting this document only back:

{
    displayTitle: "third item",
    title: "third_item",
    _type: "item",
    _parentIds: ["345", "456"]
}

Thanks!


Solution

  • The text score is 0.75. So changing match filter to greater than 0.5 works.

    Modified projection to exclude the body, _id and include parent ids.

    Created index with this query.

    db.textcol.createIndex( { displayTitle: "text" } )
    

    Running this query.

    db.textcol.aggregate([
        { $match: { $text: { $search: "item" }, _parentIds: {$in: ["345"]} }} ,
        { $project: { displayTitle: 1, title: 1, _type: 1, _id: 0, _parentIds :1, score: { $meta: "textScore" } }},
            { $match: { score: { $gt: 0.5 } } }
    ])
    

    Output:

    {
        "displayTitle": "third item",
        "title": "third_item",
        "_type": "item",
        "_parentIds": ["345", "456"],
        "score": 0.75
    }