下面列出了怎么用org.hibernate.search.query.dsl.QueryBuilder的API类实例代码及写法,或者点击链接到github查看源代码。
@Test
void performMultiResultLuceneIndexSearch() {
FullTextEntityManager fullTextSession = Search.getFullTextEntityManager(entityManager);
QueryBuilder builder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Dog.class).get();
BooleanJunction<BooleanJunction> bool = builder.bool();
bool.should(builder.keyword().wildcard().onField("name").matching("dog*").createQuery());
Query query = bool.createQuery();
FullTextQuery ftq = fullTextSession.createFullTextQuery(query, Dog.class);
List<Dog> result = (List<Dog>) ftq.getResultList();
assertAll(() -> {
assertThat(result.size()).isEqualTo(2);
assertApmSpanInformation(reporter, "name:dog*", "list");
});
}
@Override
public List<Owner> search(String searchterm) {
FullTextEntityManager fullTextEntityManager =
org.hibernate.search.jpa.Search.getFullTextEntityManager(entityManager);
QueryBuilder qb = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder().forEntity( Owner.class ).get();
org.apache.lucene.search.Query query = qb
.keyword()
.onFields("firstName", "lastName", "city", "pets.name")
.matching(searchterm)
.createQuery();
// wrap Lucene query in a javax.persistence.Query
javax.persistence.Query persistenceQuery =
fullTextEntityManager.createFullTextQuery(query, Owner.class);
// execute search
@SuppressWarnings("unchecked")
List<Owner> result = persistenceQuery.getResultList();
return result;
}
@Override
public List<Vet> search(String searchterm){
FullTextEntityManager fullTextEntityManager =
org.hibernate.search.jpa.Search.getFullTextEntityManager(entityManager);
QueryBuilder qb = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder().forEntity( Vet.class ).get();
org.apache.lucene.search.Query query = qb
.keyword()
.onFields("firstName", "lastName")
.matching(searchterm)
.createQuery();
// wrap Lucene query in a javax.persistence.Query
javax.persistence.Query persistenceQuery =
fullTextEntityManager.createFullTextQuery(query, Vet.class);
// execute search
@SuppressWarnings("unchecked")
List<Vet> result = persistenceQuery.getResultList();
return result;
}
@Test
public void queryOnSingleField() {
EntityManager em = emf.createEntityManager();
inTransaction( em, tx -> {
FullTextEntityManager ftem = Search.getFullTextEntityManager( em );
QueryBuilder qb = ftem.getSearchFactory()
.buildQueryBuilder()
.forEntity( VideoGame.class )
.get();
FullTextQuery query = ftem.createFullTextQuery(
qb.keyword().onField( "title" ).matching( "samurai" ).createQuery(),
VideoGame.class
);
List<VideoGame> videoGames = query.getResultList();
assertThat( videoGames ).onProperty( "title" ).containsExactly( "Revenge of the Samurai" );
} );
em.close();
}
@Test
public void queryOnMultipleFields() {
EntityManager em = emf.createEntityManager();
inTransaction( em, tx -> {
FullTextEntityManager ftem = Search.getFullTextEntityManager( em );
QueryBuilder qb = ftem.getSearchFactory()
.buildQueryBuilder()
.forEntity( VideoGame.class )
.get();
FullTextQuery query = ftem.createFullTextQuery(
qb.keyword().onFields( "title", "description").matching( "samurai" ).createQuery(),
VideoGame.class
);
List<VideoGame> videoGames = query.getResultList();
assertThat( videoGames ).onProperty( "title" ).containsExactly( "Revenge of the Samurai", "Tanaka's return" );
} );
em.close();
}
@Test
public void wildcardQuery() {
EntityManager em = emf.createEntityManager();
inTransaction( em, tx -> {
FullTextEntityManager ftem = Search.getFullTextEntityManager( em );
QueryBuilder qb = ftem.getSearchFactory()
.buildQueryBuilder()
.forEntity( VideoGame.class )
.get();
FullTextQuery query = ftem.createFullTextQuery(
qb.keyword().wildcard().onFields( "title", "description").matching( "sam*" ).createQuery(),
VideoGame.class
);
List<VideoGame> videoGames = query.getResultList();
assertThat( videoGames ).onProperty( "title" ).containsExactly( "Revenge of the Samurai", "Tanaka's return" );
} );
em.close();
}
@Test
public void rangeQuery() {
EntityManager em = emf.createEntityManager();
inTransaction( em, tx -> {
FullTextEntityManager ftem = Search.getFullTextEntityManager( em );
QueryBuilder qb = ftem.getSearchFactory()
.buildQueryBuilder()
.forEntity( VideoGame.class )
.get();
FullTextQuery query = ftem.createFullTextQuery(
qb.range()
.onField( "rating" )
.from( 2 )
.to( 9 )
.createQuery(),
VideoGame.class
);
List<VideoGame> videoGames = query.getResultList();
assertThat( videoGames ).onProperty( "title" ).containsOnly( "Revenge of the Samurai", "Ninja Castle" );
} );
em.close();
}
@Test
public void queryString() {
EntityManager em = emf.createEntityManager();
inTransaction( em, tx -> {
FullTextEntityManager ftem = Search.getFullTextEntityManager( em );
QueryBuilder qb = ftem.getSearchFactory()
.buildQueryBuilder()
.forEntity( VideoGame.class )
.get();
FullTextQuery query = ftem.createFullTextQuery(
ElasticsearchQueries.fromQueryString( "title:sam* OR description:sam*" ),
VideoGame.class
);
List<VideoGame> videoGames = query.getResultList();
assertThat( videoGames ).onProperty( "title" ).containsExactly( "Revenge of the Samurai", "Tanaka's return" );
} );
em.close();
}
private FullTextQuery getSearchByNameQuery(String searchTerm) {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(getEntityManager());
QueryBuilder projectQueryBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder()
.forEntity(Project.class).get();
BooleanJunction<?> booleanJunction = projectQueryBuilder.bool();
if (StringUtils.hasText(searchTerm)) {
booleanJunction.must(projectQueryBuilder
.keyword()
.fuzzy().withPrefixLength(1).withThreshold(0.8F)
.onField(Binding.project().name().getPath())
.matching(searchTerm)
.createQuery());
} else {
booleanJunction.must(projectQueryBuilder.all().createQuery());
}
return fullTextEntityManager.createFullTextQuery(booleanJunction.createQuery(), Project.class);
}
private FullTextQuery getSearchQuery(String searchTerm) {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(getEntityManager());
QueryBuilder userQueryBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder()
.forEntity(User.class).get();
BooleanJunction<?> booleanJunction = userQueryBuilder.bool();
if (StringUtils.hasText(searchTerm)) {
booleanJunction.must(userQueryBuilder
.keyword()
.fuzzy().withPrefixLength(1).withThreshold(0.8F)
.onField(Binding.user().userName().getPath())
.andField(Binding.user().fullName().getPath())
.matching(searchTerm)
.createQuery());
} else {
booleanJunction.must(userQueryBuilder.all().createQuery());
}
return fullTextEntityManager.createFullTextQuery(booleanJunction.createQuery(), User.class);
}
@Override
public List<Artifact> searchAutocomplete(String searchPattern, Integer limit, Integer offset) throws ServiceException {
String[] searchFields = new String[] {
Binding.artifact().artifactId().getPath(),
Binding.artifact().group().groupId().getPath()
};
QueryBuilder queryBuilder = Search.getFullTextEntityManager(getEntityManager()).getSearchFactory().buildQueryBuilder()
.forEntity(Artifact.class).get();
Query luceneQuery = queryBuilder.keyword().onField(Binding.artifact().deprecationStatus().getPath()).matching(ArtifactDeprecationStatus.NORMAL).createQuery();
List<SortField> sortFields = ImmutableList.<SortField>builder()
.add(new SortField(Binding.artifact().group().getPath() + '.' + ArtifactGroup.GROUP_ID_SORT_FIELD_NAME, SortField.Type.STRING))
.add(new SortField(Artifact.ARTIFACT_ID_SORT_FIELD_NAME, SortField.Type.STRING))
.build();
Sort sort = new Sort(sortFields.toArray(new SortField[sortFields.size()]));
return hibernateSearchService.searchAutocomplete(getObjectClass(), searchFields, searchPattern, luceneQuery, limit, offset, sort);
}
@Override
public List<Artifact> searchAutocompleteWithoutProject(String searchPattern, Integer limit, Integer offset) throws ServiceException {
String[] searchFields = new String[] {
Binding.artifact().artifactId().getPath(),
Binding.artifact().group().groupId().getPath()
};
QueryBuilder queryBuilder = Search.getFullTextEntityManager(getEntityManager()).getSearchFactory().buildQueryBuilder()
.forEntity(Artifact.class).get();
Query notDeprecatedQuery = queryBuilder.keyword().onField(Binding.artifact().deprecationStatus().getPath()).matching(ArtifactDeprecationStatus.NORMAL).createQuery();
Query withoutProjectQuery = queryBuilder.keyword().onField(Binding.artifact().project().getPath()).matching(null).createQuery();
BooleanJunction<?> booleanJunction = queryBuilder.bool()
.must(notDeprecatedQuery)
.must(withoutProjectQuery);
List<SortField> sortFields = ImmutableList.<SortField>builder()
.add(new SortField(Binding.artifact().group().getPath() + '.' + ArtifactGroup.GROUP_ID_SORT_FIELD_NAME, SortField.Type.STRING))
.add(new SortField(Artifact.ARTIFACT_ID_SORT_FIELD_NAME, SortField.Type.STRING))
.build();
Sort sort = new Sort(sortFields.toArray(new SortField[sortFields.size()]));
return hibernateSearchService.searchAutocomplete(getObjectClass(), searchFields, searchPattern, booleanJunction.createQuery(), limit, offset, sort);
}
public List<MagicCard> findByName(String name) {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager( em );
QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity( MagicCard.class ).get();
Query query = queryBuilder.keyword().onField( "name" ).matching( name ).createQuery();
return fullTextEntityManager.createFullTextQuery( query, MagicCard.class ).getResultList();
}
public static Member findWithEmail(EntityManager em, String email) {
FullTextEntityManager ftem = Search.getFullTextEntityManager( em );
QueryBuilder b = ftem.getSearchFactory().buildQueryBuilder().forEntity( Member.class ).get();
Query lq = b.keyword().wildcard().onField( "email" ).matching( email ).createQuery();
Object uniqueResult = ftem.createFullTextQuery( lq ).getSingleResult();
return (Member) uniqueResult;
}
@Override
public List<?> searchEntriesForUserHelper(String userId, String field,
String query, int startPosition, int maxResults) {
if (userId == null || userId.isEmpty()
|| !idGenerator.isIdWellFormed(userId)) {
return new ArrayList<Entry>();
}
if (query == null) {
return new ArrayList<Entry>();
}
if (field == null) {
return new ArrayList<Entry>();
}
FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search
.getFullTextEntityManager(getOrCreateEntityManager());
QueryBuilder qb = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder().forEntity(Entry.class).get();
org.apache.lucene.search.Query luceneQuery = qb
.bool()
.must(qb.keyword().onField(field).matching(query).createQuery())
.must(new TermQuery(new Term("userId", userId))).createQuery();
javax.persistence.Query jpaQuery = fullTextEntityManager
.createFullTextQuery(luceneQuery, Entry.class)
.setFirstResult(startPosition).setMaxResults(maxResults);
return jpaQuery.getResultList();
}
private Query createRangeQuery( QueryDef qd ) throws ParseException {
QueryBuilder builder = getFullTextSession( ).getSearchFactory( ).buildQueryBuilder( ).forEntity( entityClass ).get( );
RangeMatchingContext fieldContext = builder.range( ).onField( qd.fields[0] );
for (int i = 1; i < qd.fields.length; i++) {
fieldContext = fieldContext.andField(qd.fields[i]);
}
FromRangeContext<Object> fromContext = fieldContext.from(qd.min);
RangeTerminationExcludable toContext = qd.includeMin? fromContext.to( qd.max ) : fromContext.excludeLimit( ).to( qd.max );
return qd.includeMax ? toContext.createQuery( ) : toContext.excludeLimit( ).createQuery( );
}
@Test
public void projectionWithTransformer() {
EntityManager em = emf.createEntityManager();
inTransaction( em, tx -> {
FullTextEntityManager ftem = Search.getFullTextEntityManager( em );
QueryBuilder qb = ftem.getSearchFactory()
.buildQueryBuilder()
.forEntity( VideoGame.class )
.get();
FullTextQuery query = ftem.createFullTextQuery(
qb.keyword()
.onField( "tags" )
.matching( "round-based" )
.createQuery(),
VideoGame.class
)
.setProjection( "title", "publisher.name", "release" )
.setResultTransformer( new BasicTransformerAdapter() {
@Override
public VideoGameDto transformTuple(Object[] tuple, String[] aliases) {
return new VideoGameDto( (String) tuple[0], (String) tuple[1], (Date) tuple[2] );
}
} );
VideoGameDto projection = (VideoGameDto) query.getSingleResult();
assertThat( projection.getTitle() ).isEqualTo( "Tanaka's return" );
assertThat( projection.getPublisherName() ).isEqualTo( "Samurai Games, Inc." );
assertThat( projection.getRelease() ).isEqualTo( new GregorianCalendar( 2011, 2, 13 ).getTime() );
} );
em.close();
}
@Test
public void canSearchUsingFullTextQuery() {
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
//Add full-text superpowers to any EntityManager:
FullTextEntityManager ftem = Search.getFullTextEntityManager(entityManager);
// Optionally use the QueryBuilder to simplify Query definition:
QueryBuilder b = ftem.getSearchFactory().buildQueryBuilder().forEntity( Hike.class ).get();
// A lucene query to look for hike to the Carisbrooke castle:
// Note that the query looks for "cariboke" instead of "Carisbrooke"
Query lq = b.keyword().onField("description").matching("carisbroke castle").createQuery();
//Transform the Lucene Query in a JPA Query:
FullTextQuery ftQuery = ftem.createFullTextQuery(lq, Hike.class);
//This is a requirement when using Hibernate OGM instead of ORM:
ftQuery.initializeObjectsWith( ObjectLookupMethod.SKIP, DatabaseRetrievalMethod.FIND_BY_ID );
// List matching hikes
List<Hike> hikes = ftQuery.getResultList();
assertThat( hikes ).onProperty( "description" ).containsOnly( "Exploring Carisbrooke Castle" );
entityManager.getTransaction().commit();
entityManager.close();
}
private QueryBuilder getQueryBuilder() {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
return fullTextEntityManager.getSearchFactory()
.buildQueryBuilder()
.forEntity(Product.class)
.get();
}
private FullTextQuery getSearchByNameQuery(String searchTerm, ArtifactDeprecationStatus deprecation) {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(getEntityManager());
QueryBuilder artifactQueryBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder()
.forEntity(Artifact.class).get();
BooleanJunction<?> booleanJunction = artifactQueryBuilder.bool();
if (deprecation != null) {
booleanJunction.must(artifactQueryBuilder
.keyword()
.onField(Binding.artifact().deprecationStatus().getPath())
.matching(deprecation)
.createQuery());
}
if (StringUtils.hasText(searchTerm)) {
booleanJunction.must(artifactQueryBuilder
.keyword()
.fuzzy().withPrefixLength(1).withThreshold(0.8F)
.onField(Binding.artifact().artifactId().getPath())
.andField(Binding.artifact().group().groupId().getPath())
.matching(searchTerm)
.createQuery());
} else {
booleanJunction.must(artifactQueryBuilder.all().createQuery());
}
return fullTextEntityManager.createFullTextQuery(booleanJunction.createQuery(), Artifact.class);
}
private FullTextQuery getSearchRecommendedQuery(String searchTerm) throws ServiceException {
if (!StringUtils.hasText(searchTerm)) {
return null;
}
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(getEntityManager());
QueryBuilder artifactQueryBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder()
.forEntity(Artifact.class).get();
BooleanJunction<?> booleanJunction = artifactQueryBuilder.bool();
booleanJunction.must(artifactQueryBuilder
.keyword()
.onField(Binding.artifact().deprecationStatus().getPath())
.matching(ArtifactDeprecationStatus.NORMAL)
.createQuery());
try {
searchTerm = LuceneUtils.getSimilarityQuery(searchTerm, 2);
String[] fields = new String[] {
Binding.artifact().artifactId().getPath(),
Binding.artifact().group().groupId().getPath()
};
Analyzer analyzer = Search.getFullTextEntityManager(getEntityManager()).getSearchFactory().getAnalyzer(Artifact.class);
MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, analyzer);
parser.setDefaultOperator(MultiFieldQueryParser.AND_OPERATOR);
BooleanQuery booleanQuery = new BooleanQuery();
booleanQuery.add(parser.parse(searchTerm), BooleanClause.Occur.MUST);
booleanJunction.must(booleanQuery);
} catch (ParseException e) {
throw new ServiceException(String.format("Error parsing request: %1$s", searchTerm), e);
}
return fullTextEntityManager.createFullTextQuery(booleanJunction.createQuery(), Artifact.class);
}
/**
* Get Lucent document terms.
*/
@SuppressWarnings("unchecked")
public List<String> getTerms(Class<?> entityType, String nodeUuid) throws CorruptIndexException, IOException {
List<String> terms = new ArrayList<String>();
FullTextSession ftSession = null;
IndexSearcher searcher = null;
ReaderProvider provider = null;
Session session = null;
IndexReader reader = null;
try {
session = HibernateUtil.getSessionFactory().openSession();
ftSession = Search.getFullTextSession(session);
SearchFactory sFactory = ftSession.getSearchFactory();
provider = sFactory.getReaderProvider();
QueryBuilder builder = sFactory.buildQueryBuilder().forEntity(entityType).get();
Query query = builder.keyword().onField("uuid").matching(nodeUuid).createQuery();
DirectoryProvider<Directory>[] dirProv = sFactory.getDirectoryProviders(NodeDocument.class);
reader = provider.openReader(dirProv[0]);
searcher = new IndexSearcher(reader);
TopDocs topDocs = searcher.search(query, 1);
for (ScoreDoc sDoc : topDocs.scoreDocs) {
if (!reader.isDeleted(sDoc.doc)) {
for (TermEnum te = reader.terms(); te.next(); ) {
Term t = te.term();
if ("text".equals(t.field())) {
for (TermDocs tds = reader.termDocs(t); tds.next(); ) {
if (sDoc.doc == tds.doc()) {
terms.add(t.text());
//log.info("Field: {} - {}", t.field(), t.text());
}
}
}
}
}
}
} finally {
if (provider != null && reader != null) {
provider.closeReader(reader);
}
if (searcher != null) {
searcher.close();
}
HibernateUtil.close(ftSession);
HibernateUtil.close(session);
}
return terms;
}
@Override
public Page<Category> search(CategorySearchRequest request, Pageable pageable) {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
QueryBuilder qb = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder()
.forEntity(Category.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[] {
"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 (StringUtils.hasText(request.getLanguage())) {
junction.must(qb.keyword().onField("language").matching(request.getLanguage()).createQuery());
}
Query searchQuery = junction.createQuery();
Session session = (Session) entityManager.getDelegate();
Criteria criteria = session.createCriteria(Category.class);
Sort sort = new Sort(new SortField("sortName", SortField.Type.STRING));
FullTextQuery persistenceQuery = fullTextEntityManager
.createFullTextQuery(searchQuery, Category.class)
.setCriteriaQuery(criteria)
.setSort(sort);
if (pageable.isPaged()) {
persistenceQuery.setFirstResult((int) pageable.getOffset());
persistenceQuery.setMaxResults(pageable.getPageSize());
}
int resultSize = persistenceQuery.getResultSize();
@SuppressWarnings("unchecked")
List<Category> results = persistenceQuery.getResultList();
return new PageImpl<>(results, pageable, resultSize);
}
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("sortId", SortField.Type.LONG, false));
FullTextQuery persistenceQuery = fullTextEntityManager
.createFullTextQuery(searchQuery, User.class)
.setCriteriaQuery(criteria)
// .setProjection("id")
.setSort(sort);
if (pageable.isPaged()) {
persistenceQuery.setFirstResult((int) pageable.getOffset());
persistenceQuery.setMaxResults(pageable.getPageSize());
}
return persistenceQuery;
}
@Override
public Page<Tag> search(TagSearchRequest request, Pageable pageable) {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
QueryBuilder qb = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder()
.forEntity(Tag.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[] {
"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 (StringUtils.hasText(request.getLanguage())) {
junction.must(qb.keyword().onField("language").matching(request.getLanguage()).createQuery());
}
Query searchQuery = junction.createQuery();
Session session = (Session) entityManager.getDelegate();
Criteria criteria = session.createCriteria(Tag.class);
Sort sort = new Sort(new SortField("sortName", SortField.Type.STRING));
FullTextQuery persistenceQuery = fullTextEntityManager
.createFullTextQuery(searchQuery, Tag.class)
.setCriteriaQuery(criteria)
.setSort(sort);
persistenceQuery.setFirstResult((int) pageable.getOffset());
persistenceQuery.setMaxResults(pageable.getPageSize());
int resultSize = persistenceQuery.getResultSize();
@SuppressWarnings("unchecked")
List<Tag> results = persistenceQuery.getResultList();
return new PageImpl<>(results, pageable, resultSize);
}
public FullTextQuery buildFullTextQuery(CustomFieldSearchRequest request, Pageable pageable, Criteria criteria) {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
QueryBuilder qb = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder()
.forEntity(CustomField.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[] {
"name", "code", "description"
};
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("language").matching(request.getLanguage()).createQuery());
}
Query searchQuery = junction.createQuery();
Sort sort = new Sort(new SortField("idx", SortField.Type.INT));
FullTextQuery persistenceQuery = fullTextEntityManager
.createFullTextQuery(searchQuery, CustomField.class)
.setCriteriaQuery(criteria)
.setSort(sort);
if (pageable.isPaged()) {
persistenceQuery.setFirstResult((int) pageable.getOffset());
persistenceQuery.setMaxResults(pageable.getPageSize());
}
return persistenceQuery;
}
@Override
@PostStatusFilter
public Page<PostVO> search(Pageable pageable, String term) throws Exception {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
QueryBuilder builder = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Post.class).get();
Query luceneQuery = builder
.keyword()
.fuzzy()
.withEditDistanceUpTo(1)
.withPrefixLength(1)
.onFields("title", "summary", "tags")
.matching(term).createQuery();
FullTextQuery query = fullTextEntityManager.createFullTextQuery(luceneQuery, Post.class);
query.setFirstResult((int) pageable.getOffset());
query.setMaxResults(pageable.getPageSize());
SmartChineseAnalyzer analyzer = new SmartChineseAnalyzer();
SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<span style='color:red;'>", "</span>");
QueryScorer scorer = new QueryScorer(luceneQuery);
Highlighter highlighter = new Highlighter(formatter, scorer);
List<Post> list = query.getResultList();
List<PostVO> rets = list.stream().map(po -> {
PostVO post = BeanMapUtils.copy(po);
try {
// 处理高亮
String title = highlighter.getBestFragment(analyzer, "title", post.getTitle());
String summary = highlighter.getBestFragment(analyzer, "summary", post.getSummary());
if (StringUtils.isNotEmpty(title)) {
post.setTitle(title);
}
if (StringUtils.isNotEmpty(summary)) {
post.setSummary(summary);
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return post;
}).collect(Collectors.toList());
buildUsers(rets);
return new PageImpl<>(rets, pageable, query.getResultSize());
}
/**
* This method contains the primary search functionality for this servlet, and is automatically invoked once for every HTTP
* POST to the mapped URL.
*/
@SuppressWarnings("unchecked")
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Logger logger = LoggerFactory.getLogger(SearchServlet.class);
// Get the user's search keyword(s) from CGI variables
String searchString = request.getParameter("searchString");
logger.info("Received searchString [" + searchString + "]");
// Start a Hibernate session.
Session session = StartupDataLoader.openSession();
// Create a Hibernate Search wrapper around the vanilla Hibernate session
FullTextSession fullTextSession = Search.getFullTextSession(session);
// Begin a transaction. This may not be strictly necessary, but is a good practice in general.
fullTextSession.beginTransaction();
// Create a Hibernate Search QueryBuilder for the appropriate Lucene index (i.e. the index for "App" in this case)
QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity( App.class ).get();
// Use the QueryBuilder to construct a Lucene keyword query... matching the user's search keywords against the "name"
// and "description" fields of App, as well as "name" field of associated Device entities, and the "comments" field of
// embedded CustomerReview objects.
org.apache.lucene.search.Query luceneQuery = queryBuilder
.keyword()
.onFields("name", "description", "supportedDevices.name", "customerReviews.comments")
.matching(searchString)
.createQuery();
org.hibernate.Query hibernateQuery = fullTextSession.createFullTextQuery(luceneQuery, App.class);
List<App> apps = hibernateQuery.list();
logger.info("Found " + apps.size() + " apps");
// Detach the results from the Hibernate session (to prevent unwanted interaction between the view layer
// and Hibernate when associated devices or embedded customer reviews are referenced)
fullTextSession.clear();
// Put the search results on the HTTP reqeust object
request.setAttribute("apps", apps);
// Close and clean up the Hibernate session
fullTextSession.getTransaction().commit();
session.close();
// Forward the request object (including the search results) to the JSP/JSTL view for rendering
getServletContext().getRequestDispatcher("/WEB-INF/pages/search.jsp").forward(request, response);
}
/**
* This method contains the primary search functionality for this servlet, and is automatically invoked once for every HTTP
* POST to the mapped URL.
*/
@SuppressWarnings("unchecked")
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Logger logger = LoggerFactory.getLogger(SearchServlet.class);
// Get the user's search keyword(s) from CGI variables
String searchString = request.getParameter("searchString");
logger.info("Received searchString [" + searchString + "]");
// Start a Hibernate session.
Session session = StartupDataLoader.openSession();
// Create a Hibernate Search wrapper around the vanilla Hibernate session
FullTextSession fullTextSession = Search.getFullTextSession(session);
// Begin a transaction. This may not be strictly necessary, but is a good practice in general.
fullTextSession.beginTransaction();
// Create a Hibernate Search QueryBuilder for the appropriate Lucene index (i.e. the index for "App" in this case)
QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity( App.class ).get();
// Use the QueryBuilder to construct a Lucene keyword query, matching the user's search keywords against the name
// and description fields of App.
org.apache.lucene.search.Query luceneQuery = queryBuilder
.keyword()
.onFields("name", "description")
.matching(searchString)
.createQuery();
org.hibernate.Query hibernateQuery = fullTextSession.createFullTextQuery(luceneQuery, App.class);
// Perform the search query, and put its results on the HTTP request object
List<App> apps = hibernateQuery.list();
logger.info("Found " + apps.size() + " search results");
request.setAttribute("apps", apps);
// Close and clean up the Hibernate session
fullTextSession.getTransaction().commit();
session.close();
// Forward the request object (including the search results) to the JSP/JSTL view for rendering
getServletContext().getRequestDispatcher("/WEB-INF/pages/search.jsp").forward(request, response);
}
/**
* This method contains the primary search functionality for this servlet, and is automatically invoked once for every HTTP
* POST to the mapped URL.
*/
@SuppressWarnings("unchecked")
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Logger logger = LoggerFactory.getLogger(SearchServlet.class);
// Get the user's search keyword(s) from CGI variables
String searchString = request.getParameter("searchString");
logger.info("Received searchString [" + searchString + "]");
// Start a Hibernate session.
Session session = StartupDataLoader.openSession();
// Create a Hibernate Search wrapper around the vanilla Hibernate session
FullTextSession fullTextSession = Search.getFullTextSession(session);
// Begin a transaction. This may not be strictly necessary, but is a good practice in general.
fullTextSession.beginTransaction();
// Create a Hibernate Search QueryBuilder for the appropriate Lucene index (i.e. the index for "App" in this case)
QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity( App.class ).get();
// Use the QueryBuilder to construct a Lucene keyword query... matching the user's search keywords against the "name"
// and "description" fields of App, as well as "name" field of associated Device entities, and the "comments" field of
// embedded CustomerReview objects.
org.apache.lucene.search.Query luceneQuery = queryBuilder
.keyword()
.onFields("name", "description", "supportedDevices.name", "customerReviews.comments")
.matching(searchString)
.createQuery();
org.hibernate.Query hibernateQuery = fullTextSession.createFullTextQuery(luceneQuery, App.class);
List<App> apps = hibernateQuery.list();
logger.info("Found " + apps.size() + " apps");
// Detach the results from the Hibernate session (to prevent unwanted interaction between the view layer
// and Hibernate when associated devices or embedded customer reviews are referenced)
fullTextSession.clear();
// Put the search results on the HTTP reqeust object
request.setAttribute("apps", apps);
// Close and clean up the Hibernate session
fullTextSession.getTransaction().commit();
session.close();
// Forward the request object (including the search results) to the JSP/JSTL view for rendering
getServletContext().getRequestDispatcher("/WEB-INF/pages/search.jsp").forward(request, response);
}