提问者:小点点

包括分数在莫菲亚全文搜索


我正在尝试在摩洛哥使用MongoDB全文索引。我需要返回每个文档的分数并对结果进行排序。这是我的查询在没有摩洛哥的情况下的样子:

   db.getCollection('disease').find( { $text: { $search: "brain" } }, 
                                     { score: { $meta: "textScore" } } )
                              .sort( { score: { $meta: "textScore" } } )

这可以正常工作并返回按分数排序的命中。

我也可以直接使用MongoDBJava驱动程序来做到这一点,而不需要Morphia。

    // search with the Java driver
    BasicDBObject textSearch = new BasicDBObject("$search", "brain");
    BasicDBObject search = new BasicDBObject("$text", textSearch);

    BasicDBObject meta = new BasicDBObject("$meta", "textScore");
    BasicDBObject score = new BasicDBObject("score", meta);

    List<DBObject> diseases = collection.find(search, score).sort(score).toArray();
    Assert.assertEquals(2, diseases.size());
    Assert.assertEquals("brain", diseases.get(0).get("name"));
    Assert.assertEquals("benign-brain", diseases.get(1).get("name"));

我不知道该如何在莫菲亚完成同样的事情。以下是莫菲亚留档(http://mongodb.github.io/morphia/1.0/guides/querying/#text-searching)中的示例:

List<Greeting> good = datastore.createQuery(Greeting.class)
                             .search("good")
                             .order("_id")
                             .asList();
Assert.assertEquals(4, good.size());

该示例不返回分值,并按“_id”排序。我看不到任何方法可以处理莫菲亚中的$meta运算符。有人做过类似的事情吗?


共3个答案

匿名用户

因为在这种情况下,摩洛哥映射回你的类型,所以在这种情况下公开分数的唯一方法是向你的实体类型添加一个分数字段,并将其映射回该字段。这并不可怕,因为它开始用数据库元数据字段污染你的业务类型。你总是可以尝试映射回一个特殊的值对象类型,其中包含你想要的任何元数据。这至少可以让你的业务对象没有这些元数据。

匿名用户

根据@evanchooly和OP的建议,我能够解决这个问题的版本如下:

首先,我用搜索创建了查询。

Datastore morphiaDS = ...;
Query<myMorphiaModel> query = morphiaDS.createQuery(myMorphiaModel.class)
                .field("helloField").equal("world")
                .search("yadayadayada"); // Search performs a text search

接下来,我过渡到使用直接JavaMongo驱动程序。现在看来,虽然@evanchooly的这一期仍然开放,但我们需要使用mongo驱动程序,不能使用纯粹的莫菲亚。

BasicDBObject meta = new BasicDBObject("$meta", "textScore");
BasicDBObject score = new BasicDBObject("score", meta);
List<DBObject> results = query.getCollection()
            .find(query.getQueryObject(), score)
            .sort(score).toArray();

最后,我将广义对象列表转换为我的原始morfi模型

Morphia morphia = mongoService.getMorphia();
List<myMorphiaModel> searchDocs = results.stream()
            .map((result) -> morphia.fromDBObject(myMorphiaModel.class, result))
            .collect(Collectors.toList());

需要注意的一个故障排除问题是,我必须确保我在查找中有“分数”表示,而不仅仅是排序。

希望这澄清了其他人提出的有用答案……

匿名用户

看起来这个问题已经通过提交https://github.com/mongodb/morphia/commit/af4d64f6de3c0b1437dd216f5762d03bf98cdcb0得到了解决,现在你可以这样做了:

List<Greeting> good = datastore.createQuery(Greeting.class)
                                .search("good")
                                .project(Meta.textScore("score"))
                                .order(Meta.textScore("score"))

现在唯一需要注意的是,由于score上的项目必须能够按score排序,如果没有添加其他投影,结果只包含score字段。因此,必须将所有所需字段的投影添加到查询中。

希望这有帮助。