Стратегия запросов Lucene Cypher

Прежде всего, мы используем технологии Neo4j, Spring и Spring Data Neo4j (все последние стабильные версии).

У нас есть требование, чтобы пользователи могли искать все наши объекты отдельно, а также обеспечивать глобальный поиск для всех объектов. Я надеюсь собрать предложения о том, как реализовать глобальный поиск. Ниже приведен некоторый (упрощенный!) код, который показывает, как я запрашиваю свои сущности. Каждая сущность использует свой собственный индекс Lucene.

Структура сущности:

@NodeEntity
public abstract class BaseEntity {

    @GraphId
    private Long id;

}

@NodeEntity
public class A extends BaseEntity {

    private static final String INDEX = "A_Index";

    public static final String SEARCH_QUERY = "START a=node:" + INDEX + "({name}) RETURN a";

    @Indexed(indexType = IndexType.FULLTEXT, indexName = INDEX)
    @NotBlank
    private String name;

}

@NodeEntity
public class B extends BaseEntity {

    private static final String INDEX = "B_Index";

    public static final String SEARCH_QUERY = "START b=node:" + INDEX + "({name}) RETURN b";

    @Indexed(indexType = IndexType.FULLTEXT, indexName = INDEX)
    @NotBlank
    private String name;

}

Классы репозитория:

@Repository
public interface ARepository extends GraphRepository<A> {

    @Query(A.SEARCH_QUERY)
    List<A> find(@Param("name") String name, Pageable pageable);

}


@Repository
public interface BRepository extends GraphRepository<B> {

    @Query(B.SEARCH_QUERY)
    List<B> find(@Param("name") String name, Pageable pageable);

}

Как я получаю доступ к классам репозитория (опять же, очень упрощенно):

@Service
public class Service {

    @Autowired
    private ARepository repository;

    public List<A> search(final String name) {
        return repository.find("name:*" + name + "*", null);
    }

}

Итак, все это прекрасно работает, когда вы ищете один тип сущности. Может ли кто-нибудь предложить, как лучше всего реализовать глобальный поиск, который ищет все типы объектов?

Думает, о чем я думал:

  • Используйте один индекс Lucene вместо индекса для каждой сущности. Укажите имя поля в @Indexed, например «a.name» или «b.name». Затем используйте каждое имя поля в одном запросе, например "globalIndex:(a.name:foo ИЛИ b.name:foo). (на самом деле не уверен, возможно ли это)

  • Запустите отдельный поисковый вызов для каждого типа объекта и объедините результаты. Однако будет сложно реализовать разбиение на страницы и сортировку на основе оценки индекса.

Я не беспокоюсь о производительности, потому что мы будем использовать относительно небольшой набор данных.

Последний вопрос: всегда ли результаты, возвращаемые запросом Cypher Lucene, сортируются по индексу? Если нет, то как мне это сделать в SDN?


person tstorms    schedule 05.12.2012    source источник


Ответы (1)


Я думаю, что ваш первый вариант наиболее разумен.

В общем, вы также можете использовать indexLevel=Level.CLASS для получения глобального индекса по всем вашим объектам (или использовать одно и то же имя индекса для всех). А затем во время запроса, если вы хотите отфильтровать по типу, также добавьте фильтр where: where a.__type__ = {fqn} fqn — это полное имя (или, если вы используете @TypeAlias, это значение)

В настоящее время сортировка по счету не поддерживается, обычно шифр сортирует только по вещам, к которым вы можете получить прямой доступ в графе.

P.S. Было бы здорово иметь аннотацию, которая принимает несколько аннотаций @Indexed для одного поля, а затем учитывает их все (хотя это создаст проблемы, если вы хотите вывести индекс из поля). Не стесняйтесь поднимать вопрос в SDN JIRA.

person Michael Hunger    schedule 06.12.2012
comment
Спасибо за отзыв Михаил. Я пойду с вашим советом. Единственная проблема, которая все еще сохраняется, заключается в том, что мы хотим, чтобы наши результаты сортировались по их баллам. Можно ли это сделать, обратившись к низкоуровневому API Neo4j? - person tstorms; 06.12.2012