The method filter(FilterBuilder) in the type FilterAggregationBuilder is not applicable for the arguments (BoolQueryBuilder) - elasticsearch

Am trying to group and subgroup in an elastic query, first by ipgroup and then by priority.
TermsBuilder ipGroupAgg = AggregationBuilders.terms("by_ipGroup").field("IP Group")
.subAggregation(AggregationBuilders.terms("by_Priority").field("Priority"));
// create the bool filter for the condition above
String[] priority= { "2", "3" };
BoolQueryBuilder aggFilter = QueryBuilders.boolQuery().must(QueryBuilders.termsQuery("Priority", priority));
// create the filter aggregation and add the year sub-aggregation
FilterAggregationBuilder aggregation = AggregationBuilders.filter("agg").filter(aggFilter).subAggregation(ipGroupAgg );
But the last statement gives compile error stating "The method filter(FilterBuilder) in the type FilterAggregationBuilder is not applicable for the arguments (BoolQueryBuilder)" for the filter(aggFilter)

You're probably using an old version of ES, my guts tell me 1.7 or earlier...
In this case you need to use the following code to create aggFilter:
BoolFilterBuilder aggFilter = FilterBuilders.boolFilter().must(FilterBuilders.termsFilter("Priority", priority));

Related

How to get list of a field value as the result in mongodb with Spring Data

I want to get a list of a field's value from documents.
How can I write the following in spring
db.collection.find({"name" : "tom"}).map(function(u) return u.age)
If I use
Aggregation.match(Criteria.where("name).in("tom))
Aggregation.group("age")
I get list Objects with {_id, age} but I want List<String> ages
First things first, You don't need to map to get just the age field from the collection, you can just use projection.
Projection returns _id by default, so, you might want to specify it to be not returned if that's so.
i.e db.collection.find({}, {'age': 1, '_id': 0})
In Spring Data, you can perform a similar operation with include() and exclude().
i.e
Query query = new Query();
query.fields().include("age").exclude("id");
List<User> usersWithJustAgeInformation = mongoTemplate.find(query, User.class);
but this will also return an object of type User from which you can very easily filter the List <String> ages with stream, map and collect.
Eg.
Query query = new Query();
query.fields().include("age").exclude("id");
List<String> ages = mongoTemplate.find(query, User.class).stream().map(User::getAge).collect(Collectors.toList());
Please read https://www.baeldung.com/spring-data-mongodb-projections-aggregations for more information and examples of projection and aggregation.

Create criteria object using map in mongo

I have a map Map filterParams, whose key,value pair will be a part of a Criteria. How do I create the Criteria object.
Earlier I was using Query.addCriteria. However now I want a criteria object as I need to pass it to Aggregation.match() in mongo.
filterParams.entrySet().forEach(e -> query.addCriteria(criteria.where(e.getKey()).is(e.getValue())));
Aggregation aggregation = Aggregation.newAggregation(Aggregation.match(criteria ),Aggregation.group("property_type.name").count().as("count"),
Aggregation.project("property_type").andExclude("_id"));
Try this one:
Criteria criteria = new Criteria();
filterParams.entrySet().forEach(e -> criteria.and(e.getKey()).is(e.getValue()));
Aggregation aggregation = Aggregation.newAggregation(
Aggregation.match(criteria),
Aggregation.group("property_type.name").count().as("count"),
Aggregation.project("property_type").andExclude("_id")
);

How to use the for loop over multiple criteria in mongodb from spring

I am trying to use the for loop over the criteria in the spring Dao to return a list of documents for each scenario matched in the list:
mongoDb contains multiple documents for the same studentId with different times.
I have a Array list with studentId's and times that I want to query on mongodb
The input looks like this
List <StudentAssociation> ={{studentId:st1234,assocstarttime=2019-08-16,assocendtime:2019-08-17},{studentId:st3456,assocstarttime=2019-07-09, assocendtime=2019-08-15}}
The query I wrote for a single student working without the for loop, but I want to send the list as the input
Working query
public List<Student> getListOfStudentRecords(String studentId, LocalDateTime assocstarttime, LocalDatetime assocendtime) {
Query query = new Query();
Criteria studentIdCriteria = Criteria
.where("studentId)
.is(studentId);
Criteria dateTimeCriteria = Criteria
.where(datetime)
.gte(assocstarttime.toString())
.lte(assocendtime.toString());
query.addCriteria(studentIdCriteria);
query.addCriteria(dateTimeCriteria);
return mongoTemplate.find(query, Student.class);
}
What I am trying is input the list, the following query
public List getListofStudentRecordsUsingList(List studentAssoc) {
Query query = new Query();
//for loop
for(StudentAssociation sa : studentAssoc) {
Criteria studentIdCriteria = Criteria
.where("studentId)
.is(studentId);
Criteria dateTimeCriteria = Criteria
.where(datetime)
.gte(sa.getAssocStarttime())
.lte(sa.getAssocEndtime());
query.addCriteria(studentIdCriteria);
query.addCriteria(dateTimeCriteria);
}
query.with(new Sort(Sort.Direction.ASC, datetime));
return mongoTemplate.find(query, Student.class);
}
Expected output is for each student in the list return list of documents and then merge the result for each student into a single list and sort based on time field to create a timeline
The error I am getting withe second query is
//this is solved when I moved the Query query = new Query(); inside the for Loop
InvalidMongoDbApiUsageException: Due to limitations of the com.mongodb.BasicDocument, you can't add a second 'studentId' criteria. Query already contains '{ "lStudentId" : "st1234" }' //this is resolved when I move the query inside the for loop
Your Query object definition is outside of loop, so the same object is used for your whole loop. At second pass, query variable already contains a 'studentId' criteria, as explained in your error.
Try to set query inside loop, or clear your object at start of loop.
//for loop
for(StudentAssociation sa : studentAssoc) {
Query query = new Query();
...
Query in a loop is such an expensive thing, i would recommend you to use and & in for reduce the number of queries.
Mongodb provides operator like :
The $and operator evaluates one or more expressions and returns true if all of the expressions are true or if evoked with no argument expressions. Otherwise, $and returns false.
The $in operator selects the documents where the value of a field equals any value in the specified array.
Query findStudent = new Query(Criteria.where("studentId").in('List of id')
.and('datetime').gte('you should filter min time')
.lte('max time'))
.with(new Sort(Sort.Direction.ASC, datetime));

FOSElasticaBundle order query

I am integrating FOSElasticaBundle in my Symfony 2.3 project and I need to sort the results by their price property.
Here is my code:
$finder = $this->container->get('fos_elastica.finder.website.product');
$fieldTerms = new \Elastica\Query\Terms();
$fieldTerms->setTerms('taxon_ids', $taxon_ids_array);
$boolQuery->addMust($fieldTerms);
$resultSet = $finder->find($boolQuery);
How I can do this?
Thanks
Try create a \Elastica\Query object which also contains the sorting information, then send this to the finder:
$finder = $this->container->get('fos_elastica.finder.website.product');
$fieldTerms = new \Elastica\Query\Terms();
$fieldTerms->setTerms('taxon_ids', $taxon_ids_array);
$boolQuery->addMust($fieldTerms);
$finalQuery = new \Elastica\Query($boolQuery);
$finalQuery->setSort(array('price' => array('order' => 'asc')));
$resultSet = $finder->find($finalQuery);
Have a look at the elasticsearch docs on the sort parameter to see how to use it properly.
NOTE: \Elastica\Query is quite different to \Elastica\Query\AbstractQuery, the first encapsulates everything you could send to the _search API endpoint (facets, sorting, explain, etc...) The AbstractQuery represents a base type for each of the individual query types (range, fuzzy, terms, etc...).

How can I add an "ex" LocalParams to a Facet Field Query in SolrNet?

If I use a SolrFacetFieldQuery to build a facet query, I can't add the LocalParams in the constructor because when it parses the other facet parameters such as Limit and Sort, it will add the LocalParams to the name of the field, which generates an invalid query for example:
var fq = new SolrFacetFieldQuery(new LocalParams{{"ex", "c"}} + "category") { Limit = 10 };
I would like to generate:
facet.field={!ex=c}category&facet.category.limit=10&fq={!tag=c}category:1
This was fixed a couple of weeks ago.

Resources