Spring Mongo criteria problems with andOperator - spring

I'm trying to create a dynamic mongoDB query using spring Criteria. My query is :
Criteria.where(key1).is(value1).and(key2).is(value2)
The numbers of key/value is not fixed but can change.
I try to use andOperator but it's not for my case.
Can someone help me?

This post explains a similara problem:
Spring Mongo criteria querying twice the same field
This is what you want to do:
Criteria criteria = new Criteria().andOperator(
Criteria.where("key1").is(value1),
Criteria.where("key2").is(value2));
// to print the mongodb query for debug purposes
// System.out.println(criteria.getCriteriaObject());
// execute with a mongoTemplate
List<YourClass> documents = mongoTemplate.find(new Query(criteria), YourClass.class);

Related

How to do Rescore with Spring Data Elastic search?

I'm using spring boot with the Spring Data Elastic search client.
And I have something like
NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();
QueryBuilder nameQuery = boolQuery().should(matchQuery("fullName", queryText)).boost(10)
.should(matchQuery("fullName", queryText).fuzziness(Fuzziness.ONE)).boost(1.5f)
.should(matchQuery("fullName.autocomplete", queryText)).boost(2f)
.should(matchQuery("fullName.metaphone", queryText)).boost(1.2f)
.should(matchQuery("fullName.synonym", queryText)).boost(2)
.should(matchQuery("fullName.porter", queryText));
searchQueryBuilder.withQuery(nameQuery);
List<MasterIndex> masterIndices = masterIndexRepository.search(searchQueryBuilder.build());
After getting all of the names, I'd like to try with rescoring using some other attributes to reorder the result that might be more relevant. I know there is a rescore query, like this
RescoreBuilder.QueryRescorer rescoreBuilder = RescoreBuilder.queryRescorer(boolQuery().should(hasChildQuery("client",
QueryBuilders.boolQuery()
.should(QueryBuilders.termsQuery("enrollments.programId", programId))
))).setQueryWeight(0.7f).setRescoreQueryWeight(0.3f);
But how to put the rescoreBuilder together with NativeSearchQueryBuilder?
Or if there's any other way to customize score and order the result more intelligently, please let me know.

MongoRepository Compared two column + Spring Data

I would like to execute the query with compared two column value using mongorepository + spring data (HQL or criteria query). I am showing you relation query and i want to convert to mongo.
Select * from Employee em where em.limit < em.age
I want to convert above query to HQL query using Spring data.
You can use $where to achive this:
db.employee.find( { $where: "this. limit < this. age" } );
check out the document here:
https://docs.mongodb.com/manual/reference/operator/query/where/

How can we fetch column values which are between two limits in MongoTemplate?

for example i want to find age between 16 and 25 from a collection in mongoDB.
my query is..
Query query = new Query(Criteria.where("visibility").is(1)
.and("type").is("guide").and("age").gte(16).and("age").lte(25));
but it is giving exception. reason is mongo template do not support lte() and gte() with same column. so how can i handle it ? is their any solution ?
Try not to include an extra and("age") part in your criteria. What you need is this:
Query query = new Query(Criteria.where("visibility").is(1)
.and("type").is("guide").and("age").gte(16).lte(25));

Spring data elastic search - Query - Full text search

I am trying to use elastic search for full text search and Spring data for integrating elastic search with my application.
For example,
There are 6 fields to be indexed.
1)firstName
2)lastName
3)title
4)location
5)industry
6)email
http://localhost:9200/test/_mapping/
I can see these fields in the mapping.
Now, I would like to make a search against these fields with a search input.
For example, When I search "mike 123", it has to search against all these 6 fields.
In Spring data repository,
The below method works to search only in firstName.
Collection<Object> findByFirstNameLike(String searchInput)
But, I would like to search against all the fields.
I tried,
Collection<Object> findByFirstNameLikeOrLastNameLikeOrTitleLikeOrLocationLikeOrIndustryLikeOrEmailLike(String searchInput,String searchInput1,String searchInput2,String searchInput3,)
Here, even the input string is same, i need to pass the same input as 6 params. Also the method name looks bigger with multiple fields.
Is there anyway to make it simple with #Query or ....
Like,
Collection<Object> findByInput(String inputString)
Also, boosting should be given for one of the field.
For example,
When i search for "mike mat", if there is any match in the firstName, that should be the first one in the result even there are exact match in the other fields.
Thanks
Lets suppose your search term is in the variable query, you can use the method search in ElasticsearchRepository.
repo.search(queryStringQuery(query))
to use queryStringQuery use the following import
import static org.elasticsearch.index.query.QueryBuilders.queryStringQuery;
I found the way to achieve this and posting here. Hope, this would help.
QueryBuilder queryBuilder = boolQuery().should(
queryString("Mike Mat").analyzeWildcard(true)
.field("firstName", 2.0f).field("lastName").field("title")
.field("location").field("industry").field("email"));
Thanks
Not a spring-data elasticsearch expert. But I see two directions you can go. The first would be to use the #Query option. That way you can create your own query. The second would be to use the example in the Filter builder section:
http://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.misc.filter
Within elasticearch you would want to use the multi_match query:
http://www.elastic.co/guide/en/elasticsearch/reference/1.5/query-dsl-multi-match-query.html
In java such a query would look like this:
QueryBuilder qb = multiMatchQuery(
"kimchy elasticsearch",
"user", "message"
);
Example coming from: http://www.elastic.co/guide/en/elasticsearch/client/java-api/current/query-dsl-queries.html#multimatch
We can write our own custom query as below.
we can specific index, routing value (this is used if alias is used)
SearchQuery searchQuery = new NativeSearchQueryBuilder().withIndices(INDEX)
.withRoute(yourQueryBuilderHelper.getRouteValue())
.withQuery(yourQueryBuilderHelper.buildQuery(yourSearchFilterRequestObject))
.withFilter(yourQueryBuilderHelper.buildFilter(yourSearchFilterRequestObject)).withTypes(TYPE)
.withSort(yourQueryBuilderHelper.buildSortCriteria(yourSearchFilterRequestObject))
.withPageable(yourQueryBuilderHelper.buildPaginationCriteria(yourSearchFilterRequestObject)).build();
FacetedPage<Ticket> searchResults = elasticsearchTemplate.queryForPage(searchQuery, YourDocumentEntity.class);
Its good to use your own queryBuilder helper which can seperate your elasticSearchService from queryBuilder responsibility.
Hope this helps
Thanks
QueryBuilder class is helpful to query from spring Dao to elastic search:
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryBuilder;
QueryBuilder qb = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("state", "KA"));
.must(QueryBuilders.termQuery("content", "test4"))
.mustNot(QueryBuilders.termQuery("content", "test2"))
.should(termQuery("content", "test3"));
.should(termQuery("content", "test3"));
Try like this, you can even set importance of the field
QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(query)
.field("name", 2.0f)
.field("email")
.field("title")
.field("jobDescription", 3.0f)
.type(MultiMatchQueryBuilder.Type.PHRASE_PREFIX);
Another way is using Query String query
Query searchQuery = new StringQuery(
"{\"query\":{\"query_string\":{\"query\":\""+ your-query-here + "\"}}}\"");
SearchHits<Product> products = elasticsearchOperations.search(
searchQuery,
Product.class,
IndexCoordinates.of(PRODUCT_INDEX_NAME));
This will search all the field from your document of specified index

Getting first row from a resultset with sort by descending using QueryDsl predicate and spring jpa

I am new to spring JPA . I have one query such that i've to get the resultset and take only the row at the top.I dont know how to do it in spring JPA.And i dont want it to be done using #Query annotation,Since i was asked not to go with any queries inside the code.This is the uery i want to convert
My Query
SELECT id,name FROM example_table ORDER BY id DESC LIMIT 1;
I tried something like this in my predicate file:
public Predicate getLatest(){
QExampleTable example = QExampleTable.exampleTable;
return (Predicate) example.id.desc();
}
and this is how my jpa repository looks like:
public ExampleTable findOne(MyPredicate.getLatest());
But this is'nt working out and i know it wont clearly.But I seriously dont know how to convert this above query.Can anyone help me out with this
You can do it using just QueryDSL without Predicate and Repositories.
List<ExampleTable> examples = new JPAQuery()
.from(QExampleTable.exampleTable)
.limit(1)
.orderBy(new OrderSpecifier<>(Order.DESC, QExampleTable.exampleTable.id))
.list(QExampleTable.exampleTable);
you can use offset or limit functions.
In your case .limit(1) should be enough
This won't work because desc() returns an OrderSpecifier that must be used with Query.orderBy().
The following could work, though it's not a "pure" Predicate:
public Predicate getLatest() {
QExampleTable example = QExampleTable.exampleTable;
return example.id.eq(new JPASubQuery().from(example).unique(example.id.max()));
}
I'm afraid a more clean solution is that you provide a CustomRepository + implementation.
With QueryDSL for me, the option that is working is using max().
JPAExpressions.selectFrom(QExampleTable.exampleTable)
.select(QExampleTable.exampleTable.max())

Resources