private FullTextQuery buildFullTextQuery(
      UserSearchRequest request, Pageable pageable, Criteria criteria) {
    FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
    QueryBuilder qb =
        fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(User.class).get();

    @SuppressWarnings("rawtypes")
    BooleanJunction<BooleanJunction> junction = qb.bool();
    junction.must(qb.all().createQuery());

    if (StringUtils.hasText(request.getKeyword())) {
      Analyzer analyzer = fullTextEntityManager.getSearchFactory().getAnalyzer("synonyms");
      String[] fields =
          new String[] {
            "loginId", "name.firstName", "name.lastName",
          };
      MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, analyzer);
      parser.setDefaultOperator(QueryParser.Operator.AND);
      Query query = null;
      try {
        query = parser.parse(request.getKeyword());
      } catch (ParseException e1) {
        try {
          query = parser.parse(QueryParser.escape(request.getKeyword()));
        } catch (ParseException e2) {
          throw new RuntimeException(e2);
        }
      }
      junction.must(query);
    }

    if (!CollectionUtils.isEmpty(request.getRoles())) {
      for (User.Role role : request.getRoles()) {
        junction.must(qb.keyword().onField("roles").matching(role).createQuery());
      }
    }

    Query searchQuery = junction.createQuery();

    Sort sort = new Sort(new SortField("id", SortField.Type.STRING, false));

    FullTextQuery persistenceQuery =
        fullTextEntityManager
            .createFullTextQuery(searchQuery, User.class)
            .setCriteriaQuery(criteria)
            //				.setProjection("id")
            .setSort(sort);
    if (pageable != null) {
      persistenceQuery.setFirstResult(pageable.getOffset());
      persistenceQuery.setMaxResults(pageable.getPageSize());
    }
    return persistenceQuery;
  }
  @Override
  public Page<Comment> search(CommentSearchRequest request, Pageable pageable) {
    FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
    QueryBuilder qb =
        fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Comment.class).get();

    @SuppressWarnings("rawtypes")
    BooleanJunction<BooleanJunction> junction = qb.bool();
    junction.must(qb.all().createQuery());

    if (StringUtils.hasText(request.getKeyword())) {
      Analyzer analyzer = fullTextEntityManager.getSearchFactory().getAnalyzer("synonyms");
      String[] fields = new String[] {"authorName", "content"};
      MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, analyzer);
      parser.setDefaultOperator(QueryParser.Operator.AND);
      Query query = null;
      try {
        query = parser.parse(request.getKeyword());
      } catch (ParseException e1) {
        try {
          query = parser.parse(QueryParser.escape(request.getKeyword()));
        } catch (ParseException e2) {
          throw new RuntimeException(e2);
        }
      }
      junction.must(query);
    }

    if (StringUtils.hasText(request.getLanguage())) {
      junction.must(
          qb.keyword().onField("post.language").matching(request.getLanguage()).createQuery());
    }

    if (request.getPostId() != null) {
      junction.must(qb.keyword().onField("post.id").matching(request.getPostId()).createQuery());
    }

    if (request.getApproved() != null) {
      junction.must(qb.keyword().onField("approved").matching(request.getApproved()).createQuery());
    }

    Query searchQuery = junction.createQuery();

    Session session = (Session) entityManager.getDelegate();
    Criteria criteria =
        session
            .createCriteria(Comment.class)
            .setFetchMode("post", FetchMode.JOIN)
            .setFetchMode("author", FetchMode.JOIN);

    Sort sort = null;
    if (pageable.getSort() != null) {
      if (pageable.getSort().getOrderFor("date") != null) {
        Order order = pageable.getSort().getOrderFor("date");
        sort =
            new Sort(
                new SortField(
                    "date", SortField.Type.STRING, order.getDirection().equals(Direction.DESC)),
                new SortField(
                    "id", SortField.Type.LONG, order.getDirection().equals(Direction.DESC)));
      }
    }

    if (sort == null) {
      sort =
          new Sort(
              new SortField("date", SortField.Type.STRING),
              new SortField("id", SortField.Type.LONG));
    }

    FullTextQuery persistenceQuery =
        fullTextEntityManager
            .createFullTextQuery(searchQuery, Comment.class)
            .setCriteriaQuery(criteria)
            .setSort(sort);
    persistenceQuery.setFirstResult(pageable.getOffset());
    persistenceQuery.setMaxResults(pageable.getPageSize());

    int resultSize = persistenceQuery.getResultSize();

    @SuppressWarnings("unchecked")
    List<Comment> results = persistenceQuery.getResultList();
    return new PageImpl<>(results, pageable, resultSize);
  }
  private FullTextQuery buildFullTextQuery(
      ArticleSearchRequest request, Pageable pageable, Criteria criteria) {
    FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
    QueryBuilder qb =
        fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Article.class).get();

    @SuppressWarnings("rawtypes")
    BooleanJunction<BooleanJunction> junction = qb.bool();
    junction.must(qb.all().createQuery());

    junction.must(
        qb.keyword().onField("drafted").ignoreAnalyzer().matching("_null_").createQuery());

    if (StringUtils.hasText(request.getKeyword())) {
      Analyzer analyzer = fullTextEntityManager.getSearchFactory().getAnalyzer("synonyms");
      String[] fields =
          new String[] {
            "title", "body",
            "categories.name", "tags.name",
          };
      MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, analyzer);
      parser.setDefaultOperator(QueryParser.Operator.AND);
      Query query = null;
      try {
        query = parser.parse(request.getKeyword());
      } catch (ParseException e1) {
        try {
          query = parser.parse(QueryParser.escape(request.getKeyword()));
        } catch (ParseException e2) {
          throw new RuntimeException(e2);
        }
      }
      junction.must(query);
    }
    if (request.getStatus() != null) {
      junction.must(qb.keyword().onField("status").matching(request.getStatus()).createQuery());
    }
    if (StringUtils.hasText(request.getLanguage())) {
      junction.must(qb.keyword().onField("language").matching(request.getLanguage()).createQuery());
    }

    if (request.getDateFrom() != null) {
      junction.must(qb.range().onField("date").above(request.getDateFrom()).createQuery());
    }
    if (request.getDateTo() != null) {
      junction.must(qb.range().onField("date").below(request.getDateTo()).createQuery());
    }

    if (!CollectionUtils.isEmpty(request.getCategoryIds())) {
      BooleanJunction<BooleanJunction> subJunction = qb.bool();
      for (long categoryId : request.getCategoryIds()) {
        subJunction.should(
            qb.keyword().onField("categories.id").matching(categoryId).createQuery());
      }
      junction.must(subJunction.createQuery());
    }
    if (!CollectionUtils.isEmpty(request.getCategoryCodes())) {
      BooleanJunction<BooleanJunction> subJunction = qb.bool();
      for (String categoryCode : request.getCategoryCodes()) {
        subJunction.should(
            qb.keyword().onField("categories.code").matching(categoryCode).createQuery());
      }
      junction.must(subJunction.createQuery());
    }

    if (!CollectionUtils.isEmpty(request.getTagIds())) {
      BooleanJunction<BooleanJunction> subJunction = qb.bool();
      for (long tagId : request.getTagIds()) {
        subJunction.should(qb.keyword().onField("tags.id").matching(tagId).createQuery());
      }
      junction.must(subJunction.createQuery());
    }
    if (!CollectionUtils.isEmpty(request.getTagNames())) {
      BooleanJunction<BooleanJunction> subJunction = qb.bool();
      for (String tagName : request.getTagNames()) {
        subJunction.should(qb.phrase().onField("tags.name").sentence(tagName).createQuery());
      }
      junction.must(subJunction.createQuery());
    }

    if (request.getAuthorId() != null) {
      junction.must(
          qb.keyword().onField("author.id").matching(request.getAuthorId()).createQuery());
    }

    Query searchQuery = junction.createQuery();

    Sort sort =
        new Sort(
            new SortField("date", SortField.Type.STRING, true),
            new SortField("id", SortField.Type.LONG, true));

    FullTextQuery persistenceQuery =
        fullTextEntityManager
            .createFullTextQuery(searchQuery, Article.class)
            .setCriteriaQuery(criteria)
            .setSort(sort);
    if (pageable != null) {
      persistenceQuery.setFirstResult(pageable.getOffset());
      persistenceQuery.setMaxResults(pageable.getPageSize());
    }
    return persistenceQuery;
  }