Включить счет в полнотекстовый поиск Morphia

Я пытаюсь использовать полнотекстовые индексы MongoDB в Morphia. Мне нужно вернуть оценку для каждого документа, а также отсортировать результаты. Вот как выглядит мой запрос без Morphia:

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

Это работает правильно и возвращает попадания, отсортированные по счету.

Я также могу сделать это с помощью Java-драйвера MongoDB напрямую без 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"));

Я не могу понять, как сделать то же самое в 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». Я не вижу способа справиться с оператором $meta в Morphia. Кто-нибудь делал что-то подобное?


person Chuck M    schedule 08.06.2015    source источник


Ответы (3)


Поскольку Morphia сопоставляется с вашим типом, единственным способом показать оценку в этой ситуации будет добавление поля оценки к вашему типу сущности и сопоставление его обратно с этим полем. Это не очень хорошо, потому что это начинает загрязнять ваши бизнес-типы полями метаданных базы данных. Вы всегда можете попытаться отобразить обратно специальный тип объекта значения, содержащий любые метаданные, которые вам нужны. Это, по крайней мере, избавит ваши бизнес-объекты от этих метаданных.

person evanchooly    schedule 09.06.2015
comment
Я понимаю, что добавление оценки к типу сущности — не лучшее решение, но если я хочу, есть ли способ заставить Morphia вернуть оценку? Единственное решение, которое я вижу до сих пор, — это использовать приведенный выше пример поиска драйвера Java и вручную преобразовать DBObject в мою сущность. - person Chuck M; 09.06.2015
comment
Еще одна вещь. При использовании текстовых указателей очень важно иметь возможность упорядочивать результаты по баллам. В Морфии это кажется невозможным. - person Chuck M; 09.06.2015
comment
чтобы упорядочить по счету, не могли бы вы просто сделать .order("$score:1") ? - person evanchooly; 10.06.2015
comment
Я только что проверил это, и это не сработало. Сначала он жаловался на то, что $score является неизвестным полем. Я отключил проверку, и она возвращает результаты, но они в том же неправильном порядке, что и при отсутствии заказа. score существует только тогда, когда запрос определяет значение с помощью $meta. - person Chuck M; 10.06.2015
comment
В ПОРЯДКЕ. Похоже, мне придется копать дальше. Я подал заявку на эту тему: github.com/mongodb/morphia/issues/799 - person evanchooly; 11.06.2015

Следуя совету @evanchooly и OP, я смог решить свою версию этой проблемы следующим образом:

сначала я создал запрос вместе с поиском.

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

Затем я перешел к использованию прямых драйверов Java Mongo. Кажется, сейчас, пока эта проблема от @evanchooly все еще открыта, нам понадобится использовать драйверы монго и не может перейти на чистый морфий.

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());

Одна проблема устранения неполадок, на которую следует обратить внимание, заключается в том, что я должен был убедиться, что в находке представлен «счет», а не только в сортировке.

Надеюсь, это прояснит полезные ответы, которые представили другие....

person ThinkBonobo    schedule 08.03.2016

Похоже, эта проблема была исправлена ​​с коммитом 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. Итак, в запрос необходимо добавить проекции для всех необходимых полей.

Надеюсь это поможет.

person M Poornima    schedule 19.02.2018