@Test
  public void testSortableField() throws Exception {
    FullTextSession s = Search.getFullTextSession(openSession());
    Transaction tx = s.beginTransaction();

    Item item1 = new Item();
    item1.setId(3);
    item1.setPrice((short) 3454);
    s.persist(item1);

    Item item2 = new Item();
    item2.setId(2);
    item2.setPrice((short) 3354);
    s.persist(item2);

    Item item3 = new Item();
    item3.setId(1);
    item3.setPrice((short) 3554);
    s.persist(item3);

    tx.commit();
    s.clear();

    tx = s.beginTransaction();

    Query q =
        s.getSearchFactory().buildQueryBuilder().forEntity(Item.class).get().all().createQuery();
    FullTextQuery query = s.createFullTextQuery(q, Item.class);
    query.setSort(new Sort(new SortField("price", SortField.Type.INT)));

    List<?> results = query.list();
    assertThat(results)
        .onProperty("price")
        .describedAs("Sortable field via programmatic config")
        .containsExactly((short) 3354, (short) 3454, (short) 3554);

    query.setSort(new Sort(new SortField("id", SortField.Type.STRING)));

    results = query.list();
    assertThat(results)
        .onProperty("id")
        .describedAs("Sortable field via programmatic config")
        .containsExactly(1, 2, 3);

    s.delete(results.get(0));
    s.delete(results.get(1));
    s.delete(results.get(2));
    tx.commit();
    s.close();
  }
Пример #2
0
  /**
   * 全文检索
   *
   * @param page 分页对象
   * @param query 关键字查询对象
   * @param queryFilter 查询过滤对象
   * @param sort 排序对象
   * @return 分页对象
   */
  @SuppressWarnings("unchecked")
  public Page<T> search(Page<T> page, BooleanQuery query, BooleanQuery queryFilter, Sort sort) {

    // 按关键字查询
    FullTextQuery fullTextQuery = getFullTextSession().createFullTextQuery(query, entityClass);

    // 过滤无效的内容
    if (queryFilter != null) {
      fullTextQuery.setFilter(new CachingWrapperFilter(new QueryWrapperFilter(queryFilter)));
    }

    // 设置排序
    if (sort != null) {
      fullTextQuery.setSort(sort);
    }

    // 定义分页
    page.setCount(fullTextQuery.getResultSize());
    fullTextQuery.setFirstResult(page.getFirstResult());
    fullTextQuery.setMaxResults(page.getMaxResults());

    // 先从持久化上下文中查找对象,如果没有再从二级缓存中查找
    fullTextQuery.initializeObjectsWith(
        ObjectLookupMethod.SECOND_LEVEL_CACHE, DatabaseRetrievalMethod.QUERY);

    // 返回结果
    page.setList(fullTextQuery.list());

    return page;
  }
Пример #3
0
  @SuppressWarnings("unchecked")
  @Test
  public void testResultOrderedByIdAlteringSortStyle() throws Exception {
    Transaction tx = fullTextSession.beginTransaction();

    Query query = queryParser.parse("summary:lucene");
    FullTextQuery hibQuery = fullTextSession.createFullTextQuery(query, Book.class);

    hibQuery.setSort(new Sort(new SortField("id", SortField.Type.LONG, false)));
    List<Book> result = hibQuery.list();
    assertThat(result).onProperty("id").containsExactly(1, 2, 3, 10);

    hibQuery.setSort(new Sort(new SortField("id", SortField.Type.STRING, false)));
    result = hibQuery.list();
    assertThat(result).onProperty("id").containsExactly(1, 10, 2, 3);

    hibQuery.setSort(new Sort(new SortField("id", SortField.Type.LONG, false)));
    result = hibQuery.list();
    assertThat(result).onProperty("id").containsExactly(1, 2, 3, 10);

    tx.commit();
  }
Пример #4
0
  @SuppressWarnings("unchecked")
  @Test
  public void testResultOrderedByDocId() throws Exception {
    Transaction tx = fullTextSession.beginTransaction();

    Query query = queryParser.parse("summary:lucene");
    FullTextQuery hibQuery = fullTextSession.createFullTextQuery(query, Book.class);
    Sort sort = new Sort(new SortField(null, SortField.Type.DOC, false));
    hibQuery.setSort(sort);
    List<Book> result = hibQuery.list();

    assertNotNull(result);
    assertThat(result).onProperty("id").containsOnly(1, 2, 3, 10);

    tx.commit();
  }
Пример #5
0
  @SuppressWarnings("unchecked")
  @Test
  public void testResultOrderedByDateDescending() throws Exception {
    Transaction tx = fullTextSession.beginTransaction();

    // order by date backwards
    Query query = queryParser.parse("summary:lucene OR summary:action");
    FullTextQuery hibQuery = fullTextSession.createFullTextQuery(query, Book.class);
    Sort sort = new Sort(new SortField("publicationDate", SortField.Type.STRING, true)); // DESC
    hibQuery.setSort(sort);
    List<Book> result = hibQuery.list();
    assertNotNull(result);
    assertThat(result).onProperty("id").containsExactly(4, 10, 3, 2, 1);
    assertEquals("Groovy in Action", result.get(0).getSummary());

    tx.commit();
  }
Пример #6
0
  @SuppressWarnings("unchecked")
  @Test
  public void testResultOrderedBySummaryStringDescending() throws Exception {
    Transaction tx = fullTextSession.beginTransaction();

    // order by summary backwards
    Query query = queryParser.parse("summary:lucene OR summary:action");
    FullTextQuery hibQuery = fullTextSession.createFullTextQuery(query, Book.class);
    Sort sort = new Sort(new SortField("summary_forSort", SortField.Type.STRING, true)); // DESC
    hibQuery.setSort(sort);
    List<Book> result = hibQuery.list();
    assertNotNull(result);
    assertEquals("Wrong number of test results.", 5, result.size());
    assertEquals("Hibernate & Lucene", result.get(0).getSummary());

    tx.commit();
  }
 @Override
 public StorageResults visit(OrderBy orderBy) {
   TypedExpression field = orderBy.getExpression();
   if (field instanceof Field) {
     FieldMetadata fieldMetadata = ((Field) field).getFieldMetadata();
     SortField sortField =
         new SortField(
             fieldMetadata.getName(),
             getSortType(fieldMetadata),
             orderBy.getDirection() == OrderBy.Direction.DESC);
     query.setSort(new Sort(sortField));
     return null;
   } else {
     throw new NotImplementedException(
         "No support for order by for full text search on non-field.");
   }
 }
Пример #8
0
 /**
  * 生成Hibernate的FullTextQuery全文搜索对象。
  *
  * @return 返回Hibernate的FullTextQuery全文搜索对象。
  */
 public FullTextQuery generateQuery() {
   FullTextQuery fullTextQuery = session.createFullTextQuery(generateLuceneQuery(), clazz);
   if (!sortFields.isEmpty()) {
     for (SortField sortField : sortFields) {
       if (!searchFields.containsKey(sortField.getField())) {
         throw new HibernateException("全文搜索时指定的排序字段 " + sortField.getField() + " 必须包含在搜索字段中");
       }
     }
     fullTextQuery.setSort(new Sort(sortFields.toArray(new SortField[] {})));
   }
   if (filter != null) {
     fullTextQuery.setFilter(filter);
   }
   if (criteriaQuery != null) {
     fullTextQuery.setCriteriaQuery(criteriaQuery);
   }
   return fullTextQuery;
 }
Пример #9
0
  @SuppressWarnings("unchecked")
  @Test
  public void testCustomFieldComparatorDescendingSort() {
    Transaction tx = fullTextSession.beginTransaction();

    Query query = new MatchAllDocsQuery();
    FullTextQuery hibQuery = fullTextSession.createFullTextQuery(query, NumberHolder.class);
    Sort sort = new Sort(new SortField("sum", new SumFieldComparatorSource(), true));
    hibQuery.setSort(sort);
    List<NumberHolder> result = hibQuery.list();
    assertNotNull(result);
    assertEquals("Wrong number of test results.", 4, result.size());

    int previousSum = 100;
    for (NumberHolder n : result) {
      assertTrue("Documents should be ordered by decreasing sum", previousSum > n.getSum());
      previousSum = n.getSum();
    }

    tx.commit();
  }
 @Override
 public StorageResults visit(Select select) {
   // TMDM-4654: Checks if entity has a composite PK.
   Set<ComplexTypeMetadata> compositeKeyTypes = new HashSet<ComplexTypeMetadata>();
   // TMDM-7496: Search should include references to reused types
   Collection<ComplexTypeMetadata> types =
       new HashSet<ComplexTypeMetadata>(select.accept(new SearchTransitiveClosure()));
   for (ComplexTypeMetadata type : types) {
     if (type.getKeyFields().size() > 1) {
       compositeKeyTypes.add(type);
     }
   }
   if (!compositeKeyTypes.isEmpty()) {
     StringBuilder message = new StringBuilder();
     Iterator it = compositeKeyTypes.iterator();
     while (it.hasNext()) {
       ComplexTypeMetadata compositeKeyType = (ComplexTypeMetadata) it.next();
       message.append(compositeKeyType.getName());
       if (it.hasNext()) {
         message.append(',');
       }
     }
     throw new FullTextQueryCompositeKeyException(message.toString());
   }
   // Removes Joins and joined fields.
   List<Join> joins = select.getJoins();
   if (!joins.isEmpty()) {
     Set<ComplexTypeMetadata> joinedTypes = new HashSet<ComplexTypeMetadata>();
     for (Join join : joins) {
       joinedTypes.add(join.getRightField().getFieldMetadata().getContainingType());
     }
     for (ComplexTypeMetadata joinedType : joinedTypes) {
       types.remove(joinedType);
     }
     List<TypedExpression> filteredFields = new LinkedList<TypedExpression>();
     for (TypedExpression expression : select.getSelectedFields()) {
       if (expression instanceof Field) {
         FieldMetadata fieldMetadata = ((Field) expression).getFieldMetadata();
         if (joinedTypes.contains(fieldMetadata.getContainingType())) {
           TypeMapping mapping =
               mappings.getMappingFromDatabase(fieldMetadata.getContainingType());
           filteredFields.add(
               new Alias(
                   new StringConstant(StringUtils.EMPTY),
                   mapping.getUser(fieldMetadata).getName()));
         } else {
           filteredFields.add(expression);
         }
       } else {
         filteredFields.add(expression);
       }
     }
     selectedFields.clear();
     selectedFields.addAll(filteredFields);
   }
   // Handle condition
   Condition condition = select.getCondition();
   if (condition == null) {
     throw new IllegalArgumentException("Expected a condition in select clause but got 0.");
   }
   // Create Lucene query (concatenates all sub queries together).
   FullTextSession fullTextSession = Search.getFullTextSession(session);
   Query parsedQuery = select.getCondition().accept(new LuceneQueryGenerator(types));
   // Create Hibernate Search query
   Set<Class> classes = new HashSet<Class>();
   for (ComplexTypeMetadata type : types) {
     String className = ClassCreator.getClassName(type.getName());
     try {
       ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
       classes.add(contextClassLoader.loadClass(className));
     } catch (ClassNotFoundException e) {
       throw new RuntimeException("Could not find class '" + className + "'.", e);
     }
   }
   FullTextQuery fullTextQuery =
       fullTextSession.createFullTextQuery(
           parsedQuery, classes.toArray(new Class<?>[classes.size()]));
   // Very important to leave this null (would disable ability to search across different types)
   fullTextQuery.setCriteriaQuery(null);
   fullTextQuery.setSort(Sort.RELEVANCE); // Default sort (if no order by specified).
   query =
       EntityFinder.wrap(
           fullTextQuery,
           (HibernateStorage) storage,
           session); // ensures only MDM entity objects are returned.
   // Order by
   for (OrderBy current : select.getOrderBy()) {
     current.accept(this);
   }
   // Paging
   Paging paging = select.getPaging();
   paging.accept(this);
   pageSize = paging.getLimit();
   boolean hasPaging = pageSize < Integer.MAX_VALUE;
   if (!hasPaging) {
     return createResults(query.scroll(ScrollMode.FORWARD_ONLY));
   } else {
     return createResults(query.list());
   }
 }