在Morphia全文搜索中包含分数

时间:2015-06-08 12:43:08

标签: mongodb morphia

我正在尝试在Morphia中使用MongoDB全文索引。我需要返回每个文档的分数,并将结果排序。如果没有Morphia,这就是我的查询:

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

这样可以正常工作并返回按分数排序的匹配。

我也可以在没有Morphia的情况下直接使用MongoDB Java驱动程序。

    // 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"));

我无法弄清楚如何在Morphia中完成同样的事情。以下是Morphia文档(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”排序。我没有看到任何方法来处理Morphia中的$ meta运算符。有没有人做过类似的事情?

3 个答案:

答案 0 :(得分:2)

由于Morphia映射回您的类型,在这种情况下公开分数的唯一方法是将分数字段添加到您的实体类型并将其映射回该字段。这并不令人敬畏,因为它开始使用数据库元数据字段污染您的业务类型。您总是可以尝试映射出包含您喜欢的任何元数据的特殊值对象类型。这至少可以使您的业务对象不受此元数据的影响。

答案 1 :(得分:0)

根据@evanchooly和OP的建议,我能够按如下方式解决我的问题:

首先我通过搜索创建了查询。

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

接下来,我转而使用直接Java Mongo驱动程序。现在看来,虽然this issue by @evanchooly仍处于打开状态,但我们需要使用mongo驱动程序而不能使用纯粹的morphia。

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

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

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

需要注意的一个疑难解答问题是,我必须确保自己得分&#39;在查找中表示,而不仅仅是在排序中。

希望这能澄清其他人提出的有用答案......

答案 2 :(得分:0)

看起来此问题已通过提交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字段。因此,必须将所有必需字段的投影添加到查询中。

希望这有帮助。