@Override
  public QueryResponse query(SearchQuery searchQuery) {
    try {
      if (logger.isDebugEnabled()) {
        logger.debug("searching query...");
      }
      long start = System.currentTimeMillis();
      QueryParser queryParser =
          new QueryParser(
              LuceneConfig.LUCENE_VERSION, schema.getDefaultSearchField(), schema.getAnalyzer());
      Query query = queryParser.parse(searchQuery.getQuery());
      int pageNo = searchQuery.getPageNo();
      int pageSize = searchQuery.getPageSize();
      int fullPageCount = pageNo * pageSize;
      int pageStartIndex = pageNo < 1 ? 0 : ((pageNo - 1) * pageSize);
      Sort sort = getSort(searchQuery);
      Filter filter = getFilter(searchQuery);
      TopFieldDocs topFieldDocs = indexSearcher.search(query, filter, fullPageCount, sort);
      ScoreDoc[] scoreDocs = topFieldDocs.scoreDocs;
      int scoreDocsLength = scoreDocs.length;
      List<OutputDocument> outputDocuments;

      if (scoreDocsLength <= pageStartIndex) {
        // 当前页没有数据了
        outputDocuments = CollectionUtil.newArrayList(0);
      } else {
        // 只获取最后一页的数据
        outputDocuments = CollectionUtil.newArrayList(scoreDocs.length - pageStartIndex);
        for (int i = pageStartIndex; i < scoreDocs.length; ++i) {
          Document doc = indexSearcher.doc(scoreDocs[i].doc);
          OutputDocument outputDocument = DocumentTransformUtil.toOutputDocument(doc, schema);
          outputDocuments.add(outputDocument);
        }
      }
      QueryResponse queryResponse = new QueryResponse();

      queryResponse.setOutputDocuments(outputDocuments);
      queryResponse.setTotalHits(topFieldDocs.totalHits);

      if (logger.isDebugEnabled()) {
        logger.debug("search query finish.");
      }
      long end = System.currentTimeMillis();
      long timeEscape = end - start;
      queryResponse.setTimeEscape(timeEscape);
      return queryResponse;
    } catch (Exception e) {
      logger.error("search query error", e);
      return new QueryResponse(e.getMessage(), ResultCodes.COMMON_ERROR);
    }
  }
  @Override
  public DeleteResponse deleteByIds(List<String> ids) {
    if (CollectionUtil.isEmpty(ids)) {
      return new DeleteResponse();
    }

    final String idName = schema.getIdName();
    Term[] terms = new Term[ids.size()];
    int index = 0;
    for (String id : ids) {
      terms[index++] = new Term(idName, id);
    }
    try {
      if (logger.isDebugEnabled()) {
        logger.debug("deleting documents...");
      }
      indexWriter.deleteDocuments(terms);
      updateCount.addAndGet(ids.size());
      if (logger.isDebugEnabled()) {
        logger.debug("delete documents finish.");
      }
    } catch (IOException e) {
      logger.error("delete error", e);
      return new DeleteResponse(e.getMessage(), ResultCodes.COMMON_ERROR);
    }
    return new DeleteResponse();
  }
  private Sort getSort(SearchQuery searchQuery) {
    List<FieldSort> fieldSorts = searchQuery.getFieldSorts();

    Sort sort;
    if (CollectionUtil.isEmpty(fieldSorts)) {
      sort = Sort.RELEVANCE;
    } else {
      sort = new Sort();
      SortField[] targetSorts = new SortField[fieldSorts.size()];
      int i = 0;
      for (FieldSort fieldSort : fieldSorts) {
        String name = fieldSort.getName();
        FieldInfo fieldInfo = schema.getFieldInfos().get(name);
        boolean orderOfDesc = (fieldSort.getOrder() == FieldSort.DESC);
        SortField sortField =
            new SortField(name, fieldInfo.getFieldType().getSortType(), orderOfDesc);
        targetSorts[i++] = sortField;
      }
      sort.setSort(targetSorts);
    }
    return sort;
  }