How to query lucene for 2 index fields? - java

I'd like to execute queries with lucene. But the lookup should not only be based on the input, but also on a 2nd parameter.
Example: imagine the lucene index should contain citynames and countrycodes.
Now, during lookup I already know which country the desired cityname should be in.
SO I want to query the lucene index by cityname, but tell lucene to only look on the citynames where the countrycode matches.
It it possibel? If yes, how?
For a single attribute I would just set up the following:
QueryParser q = QueryParser(Version matchVersion, String f, Analyzer a)
Query q = queryParser.parse(input);
But how for 2 attributes?

Something like this should work. Untested but you should get the idea:
String countryCode = ....; // known in advance
QueryParser queryParser = new QueryParser(matchVersion, f, a);
Query cityNameQuery = queryParser.parse(inputWithCityName);
Query countryCodeQuery = queryParser.parse("+countrycode:" + countryCode);
BooleanQuery result = new BooleanQuery();
result.add(new BooleanClause(cityNameQuery, MUST));
result.add(new BooleanClause(countryCodeQuery, MUST));

Related

How to get data from raw query in spring boot?

I have a query:
Query q = em.createNativeQuery("select DISTINCT id, rating, random() as ordering FROM table\n" +
" WHERE id not in (1,2) ORDER BY ordering LIMIT 10");
List data = q.getResultList();
Every element of this list is array like object:
I want to retrieve that "8" and "16" and compose a comma separated string (to use it in my query in "not in" section in future):
for (Object x : data) {
System.out.println(Arrays.asList(x).get(0));
}
But it produces strings:
[Ljava.lang.Object;#ee93cd3
[Ljava.lang.Object;#62f3c3e1
I don't know how to get that IDs ("8" and "16")
1.I think this is what you are looking for...
Convert JPA query.getResultList() to MY Objects.
or
List<Object[]> rows = q.getResultList(); for (Object[] row : rows) { System.out.println(row[0]); }
in this line
List<Object[]> data = q.getResultList();
data is list of Object of form
[ [1,233, 0.000333], [1,233, 0.000333] ]
for (Object[] x : data) {
// x is [1,233, 0.000333]
System.out.println(x[0]);
}
If I understood it correctly, you are looking for comma separated string of ID's.
If so, then follow these steps might help you to solve the issue.
Create a constructor in table which has only one parameter ID. (If you want you can add more parameters as well but make sure the value which you want it must be in constructor as well as in query.)
Write sql query and execute it.
It returns result and gather it in List which contains the object of the table.
Get the string
dataList.stream().map(obj -> obj.getId()).collect(Collectors.joining(", "))
This will give you the comma separated string.

How do I search partial words in Lucene when using MultiFieldQueryParser?

public SearchResult search(String queryStr, SortBy sortBy, int maxCount)
throws ParseException, IOException {
String[] fields = {Indexer.TITLE_FIELD_NAME, Indexer.REVIEW_FIELD_NAME, "name"};
QueryParser parser = new MultiFieldQueryParser(fields, analyzer);
Query query = parser.parse(queryStr);
Sort sort = null;
if (sortBy != null) {
sort = sortBy.sort;
}
return searchAfter(null, query, sort, maxCount);
}
Above method just gives me the result, but for that I have to search for the whole word but if I search partial word it doesn't work.
By default MultiFieldQueryParser (and QueryParser, which this class inherits from) will look for the whole words you are searching, however it can also generate wildcard queries. The word "elephant" can be matched by using elep*, elep?ant (i.e. ? mathes a single letter) or ele*nt. You can also use fuzzy queries, like elechant~.
You can read the whole syntax specification here: http://lucene.apache.org/core/7_5_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html (below the class list).

Spring-data-elasticsearch search for specific fields in multiple indices

I try to search specific fields in multiple indices. I have two indices country and region. Both of the indices have a Field called name.
I am able to specify my field name and my indices in my query using elasticsaerchTemplate:
#Override
public Page<SearchHit> searchAllTest(String text) {
QueryBuilder queryBuilder = QueryBuilders.boolQuery()
.should(QueryBuilders.queryStringQuery(text).field("name"));
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
.withQuery(queryBuilder)
.withIndices("region", "country").build();
ResultsExtractor<Page<SearchHit>> rs = new ResultsExtractor<Page<SearchHit>>() {
#Override
public Page<SearchHit> extract(SearchResponse response) {
List<SearchHit> hits = Arrays.asList(response.getHits().getHits());
return new PageImpl<SearchHit>(hits, PageRequest.of(0, 10), response.getHits().getTotalHits());
}
};
return elasticsearchTemplate.query(nativeSearchQuery, rs);
}
This code works and searches for the field name in both of the indices. But I would like to specify the field name in index region and give for example a boost.
In simple words:
Field name belongs to index region and get a boost.
Field name belongs to index country and get no boost.
Is there a way to specify a field for a particular index?
Try to use withIndexBoost method:
NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder()
.withQuery(queryBuilder)
.withIndicesBoost(Arrays.asList(new IndexBoost[] {new IndexBoost("region", 2.0f)}))
.withIndices("region", "country").build();

Hibernate search : single search term with space

I am a newbie to hibernate search.
I am trying to implement a engine in which the results are exact matches.
My persistence class changes
#Field(index=Index.UN_TOKENIZED, store=Store.NO)
private String offerTitle;
Implementation changes
String[] offerFields = new String[] { "offerTitle"};
MultiFieldQueryParser parser = new MultiFieldQueryParser(Version.LUCENE_31,offerFields,new KeywordAnalyzer());
org.apache.lucene.search.Query query = parser.parse(queryString);
org.hibernate.Query offerHibQuery = fullTextSession.createFullTextQuery(query, Offer.class);
List<?> offerResults = offerHibQuery.list();
It works fine until the search term has space in it. When search term contains space, it gets no results.
For example: For the search term: "Comcast offer name" I get no results, and the query is broken into offerTitle:Comcast offerTitle:offer offerTitle:name
Is there any way to search for exact match with spaces?
I tried this:
QueryBuilder queryBuilder_1 = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Offer.class).get();
org.apache.lucene.search.Query offerCode_1 = queryBuilder_1.phrase().onField("offerTitle").sentence(queryString).createQuery();
org.hibernate.Query offerCodeHibQuery = fullTextSession.createFullTextQuery(offerCode_1);
List<?> offerCodeResults = offerCodeHibQuery.list();
It is still not working.
You are not tokenizing the field, so you need to search with a single, unanalyzed term. The simplest way to do that, I find, is to go straight to the Lucene APIs and just construct a TermQuery, like:
Query query = new TermQuery(new Term("offerTitle", queryString));
I think this should also work:
queryBuilder_1.keyword().onField("offerTitle").matching(queryString).createQuery();
queryBuilder_1.phrase().withSlop(0)
.onField("offerTitle").sentence(queryString).createQuery()

Is it possible to search for same value on multiple columns with Hibernate Criteria?

I have search query that has many optional parameters and then search word field that searches many columns. Is it possible to use hibernate criteria for this purpose? I need to search many columns with same search word.
Example code (what is not working correctly)
if(isNotEmpty(searchWord))
{
criteria.add(Restrictions.like("description", searchWord));
criteria.add(Restrictions.like("name", searchWord));
}
It looks like you actually need an OR:
Criterion description = Restrictions.like("description", searchWord);
Criterion name = Restrictions.like("name", searchWord);
LogicalExpression orExp = Restrictions.or(description, name);
criteria.add(orExp);
by using Disjunction we have add any number of columns and finally add the Disjunction obj to criteria.
Disjunction disCriteria = Restrictions.disjunction();
disCriteria.add(Restrictions.eq("name", searchWord));
disCriteria.add(Restrictions.eq("description", searchWord));
criteria.add(disCriteria);
I solved this with using custom sql restrictions, example here:
Object[] values = { }; // values here
Type[] types = { }; // value types here
criteria.add(Restrictions.sqlRestriction("sql query here", values, types));

Categories

Resources