How can I add an "ex" LocalParams to a Facet Field Query in SolrNet? - 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.

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.

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));

Mongodb Retrieve records based on only day and month

I am new in writing aggregate queries in Mongo DB + Spring
Scenario: We are storing birthDate(Jjava.uti.Date) in mongo db which got stored as ISO date. Now we are trying to look for the records which are matching with the dayOfMonth and Month only. So that we can corresponding object from the list.
I had gone through few solutions and here is the way I am trying but this is giving me a null set of records.
Aggregation agg = Aggregation.newAggregation(
Aggregation.project().andExpression("dayOfMonth(birthDate)").as("day").andExpression("month(birthDate)")
.as("month"),
Aggregation.group("day", "month"));
AggregationResults<Employee> groupResults = mongoTemplate.aggregate(agg, Employee.class, Employee.class);
I also tried applying a a query with the help of Criteria but this is also giving me a Employee object which all null content.
Aggregation agg = Aggregation.newAggregation(Aggregation.match(Criteria.where("birthDate").lte(new Date())), Aggregation.project().andExpression("dayOfMonth(birthDate)").as("day").andExpression("month(birthDate)")
.as("month"),
Aggregation.group("day", "month"));
AggregationResults<Employee> groupResults = mongoTemplate.aggregate(agg, Employee.class, Employee.class);
I must missing some important thing which is giving me these null data.
Additional Info: Employee object has only birthDate(Date) and email(String) in it
Please try to specify the fields to be included in the $project stage.
project("birthDate", "...").andExpression("...
The _id field is, by default, included in the output documents. To include any other fields from the input documents in the output documents, you must explicitly specify the inclusion in $project.
see: MongoDBReference - $project (aggregation)
I've created DATAMONGO-2200 to add an option to project directly onto the fields of a given domain type via something like project(Employee.class).

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

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));

Substring with spacebar search in RavenDB

I'm using such a query:
var query = "*" + QueryParser.Escape(input) + "*";
session.Query<User, UsersByEmailAndName>().Where(x => x.Email.In(query) || x.DisplayName.In(query));
With the support of a simple index:
public UsersByEmailAndName()
{
Map = users => from user in users
select new
{
user.Email,
user.DisplayName,
};
}
Here I've read that:
"By default, RavenDB uses a custom analyzer called
LowerCaseKeywordAnalyzer for all content. (...) The default values for
each field are FieldStorage.No in Stores and FieldIndexing.Default in
Indexes."
The index contains fields:
DisplayName - "jarek waliszko" and Email - "my_email#domain.com"
And finally the thing is:
If the query is something like *_email#* or *ali* the result is fine. But while I use spacebar inside e.g. *ek wa*, nothing is returned. Why and how to fix it ?
Btw: I'm using RavenDB - Build #960
Change the Index option for the fields you want to search on to be Analyzed, instead of Default
Also, take a look here:
http://ayende.com/blog/152833/orders-search-in-ravendb
Lucene’s query parser interprets the space in the search term as a break in the actual query, and doesn’t include it in the search.
Any part of the search term that appears after the space is also disregarded.
So you should escape space character by prepending the backslash character before whitespace character.
Try to query *jarek\ waliszko*.
So.., I've came up with an idea how to do it. I don't know if this is the "right way" but it works for me.
query changes to:
var query = string.Format("*{0}*", Regex.Replace(QueryParser.Escape(input), #"\s+", "-"));
index changes to:
public UsersByEmailAndName()
{
Map = users => from user in users
select new
{
user.Email,
DisplayName = user.DisplayName.Replace(" ", "-"),
};
}
I've just changed whitespaces into dashes for the user input text and spacebars to dashes in the indexed display name. The query gives expected results right now. Nothing else really changed, I'm still using LowerCaseKeywordAnalyzer as before.

Resources