MongoDB 通过 $in 命令获取匹配数

MongoDB get number of matches by $in command

定义

我正在创建搜索应用程序,mongo 数据库用于存储搜索信息。这是集合 "Resource".

的示例数据集
{
   _id:"5b3b84e02360a26f9a9ae96e",
   name:"Advanced Java",
   keywords:[
      "java", "thread", "state", "public", "void"
   ] 
},
{
   _id:"5b3b84e02360a26f9a9ae96f",
   name:"Java In Simple",
   keywords:[
      "java", "runnable", "thread", "sleep", "array"
   ]
}

这包含每本书的名称和最常用的单词(在关键字数组中)。我正在使用 spring 框架和 mongo 模板。如果我 运行 下面的代码,

MongoOperations mongoOperations = new MongoTemplate(new MongoClient("127.0.0.1", 27017), "ResourceDB");
Query query = new Query(where("keywords").in("java", "thread", "sleep"));
List<Resource> resources = mongoOperations.find(query, Resource.class);

结果 "Advanced Java" 和 "Java In Simple" 都正常。

问题

但就我而言,我需要按顺序使用它们。因为 "Java In Simple" 匹配 3 个词而 "Advanced Java" 只匹配 2 个词。所以最相关的书的可能性应该是 "Java In Simple" 并且它应该排在第一位。

期待订单

是否可以按匹配的顺序得到结果。或者有什么方法可以获取每个项目的匹配项数。例如,如果搜索 ("java"、"thread"、"sleep"),我希望输出如下所示。

感谢任何帮助。

$in 不匹配 3 或 2 项。它在第一场比赛后停止。您需要使用聚合管道从查询中计算 intersection 关键字和数组,并按结果大小排序:

db.collection.aggregate([
    { $addFields: {
        matchedTags: { $size: { 
            $setIntersection: [ "$keywords", [ "java", "thread", "sleep" ] ] 
        } }
    } },
    { $match: { matchedTags: { $gt: 0 } } },
    { $sort: { matchedTags: -1 } }
])

这是给那些在 java 中寻找 运行 @Alex Blex 查询的人的。看起来 mongo 模板没有交集的实现。所以我使用 mongoDB java 客户端完成了它。

List<String> keywords = Arrays.asList("java", "thread", "sleep");
BasicDBList intersectionList = new BasicDBList();
intersectionList.add("$keywords");
intersectionList.add(keywords);

AggregateIterable<Document> aggregate = new MongoClient("127.0.0.1", 27017).getDatabase("ResourceDB").getCollection("Resource").aggregate(
            Arrays.asList(
                    new BasicDBObject("$addFields",
                            new BasicDBObject("matchedTags",
                                    new BasicDBObject("$size",
                                            new BasicDBObject("$setIntersection", intersectionList)))),
                    new BasicDBObject("$match",
                            new BasicDBObject("matchedTags",
                                    new BasicDBObject("$gt", 0))),
                    new BasicDBObject("$sort",
                            new BasicDBObject("matchedTags", -1))
            )
    );
 MongoCursor<Document> iterator = aggregate.iterator();
 while (iterator.hasNext()){
        Document document = iterator.next();
        System.out.println(document.get("name")+" - "+document.get("matchedTags"));
 }