1

我正在熟悉 Lucene 和 MongoDB Atlas 搜索,并且我对查询效率有疑问。

这些查询中的哪一个使用较少的资源?

如果对执行以下任务有更好的查询,请告诉我。

我想返回与标题值匹配的所有电影(sample_mflix)。电影必须是特定年份的(不应返回任何不属于该年份的电影),我想返回movies.awards.nominations & movies.awards.wins 的“$gte”值的电影。

第一个查询似乎更复杂(这似乎增加了资源利用率 - 查询复杂性?)。此查询也不只返回该年份的值。这让我认为 Atlas 搜索可能有更好的方法来做到这一点。

第二个查询在不同阶段使用 $search 和 $match。它有一个简单的 Lucene 搜索(可能会返回比第一个查询更多的电影?),并且匹配运算符将过滤结果。第二个查询更精确 - 从我的测试来看,它尊重年份约束。如果我应用限制阶段,这会是更好的解决方案吗?

如果这些查询是在相同的场景中执行的,哪一个会更有效,为什么(抱歉,第二个查询是为 .net 驱动程序格式化的)?

new BsonArray
{
    new BsonDocument("$search", 
    new BsonDocument
        {
            { "index", "nostoreindex" }, 
            { "compound", 
    new BsonDocument
            {
                { "must", 
    new BsonDocument("near", 
    new BsonDocument
                    {
                        { "path", "year" }, 
                        { "origin", 2000 }, 
                        { "pivot", 1 }
                    }) }, 
                { "must", 
    new BsonDocument("text", 
    new BsonDocument
                    {
                        { "query", "poor" }, 
                        { "path", "title" }
                    }) }, 
                { "should", 
    new BsonDocument("range", 
    new BsonDocument
                    {
                        { "path", "awards.nominations" }, 
                        { "gte", 1 }
                    }) }, 
                { "should", 
    new BsonDocument("range", 
    new BsonDocument
                    {
                        { "path", "awards.wins" }, 
                        { "gte", 1 }
                    }) }
            } }
        })
}

VS

var searchStage =
                new BsonDocument("$search",
                    new BsonDocument
                        {
                            { "index", "nostoreindex" },
                            { "text",
                    new BsonDocument
                            {
                                { "query", title },
                                { "path", "title" }
                            } }
                        });
            var matchStage = new BsonDocument("$match",
            new BsonDocument("$and",
            new BsonArray
                    {
                new BsonDocument("year",
                new BsonDocument("$eq", year)),
                new BsonDocument("awards.nominations",
                new BsonDocument("$gte", nominations)),
                new BsonDocument("awards.wins",
                new BsonDocument("$gte", awards))
                    })
            );
4

1 回答 1

0

使用 Atlas Search 时,最好避免在您的阶段$match之后使用后续过滤器。$search这是因为所有数据都需要通过 id 在你的 mongod 中查找,这可能会很慢。

因此,一般来说,如果可能,您会尝试将搜索和过滤器保留在“Lucene”中,以避免额外的 IO 和比较。

在您的情况下,您使用nearwhich 将按从近的顺序返回所有结果。您应该改用range可以过滤这些结果并加快查询速度的方法。

near如果结果更接近特定值,则用于对结果进行更高的评分,这可以模拟排序。例如,如果您想用更高的 'awards.wins' 对结果进行评分,您可能希望添加 a ,near : { origin: 10000, pivot: 1}那么该值越接近10000分数越高。

new BsonArray
{
    new BsonDocument("$search", 
    new BsonDocument
        {
            { "index", "nostoreindex" }, 
            { "compound", 
    new BsonDocument
            {
                { "must", 
    new BsonDocument("range", 
    new BsonDocument
                    {
                        { "path", "year" }, 
                        { "gte", 2000 }, 
                        { "lte", 2000 }
                    }) }, 
                { "must", 
    new BsonDocument("text", 
    new BsonDocument
                    {
                        { "query", "poor" }, 
                        { "path", "title" }
                    }) }, 
                { "should", 
    new BsonDocument("range", 
    new BsonDocument
                    {
                        { "path", "awards.nominations" }, 
                        { "gte", 1 }
                    }) }, 
                { "should", 
    new BsonDocument("range", 
    new BsonDocument
                    {
                        { "path", "awards.wins" }, 
                        { "gte", 1 }
                    }) }
            } }
        })
}
于 2020-08-31T19:23:54.430 回答