How to make a cutomized query to Solr with Spring? - java

I am trying to retrieve some data I stored before from Solr. This is my model.
#SolrDocument(solrCoreName = "images")
public class Imagen {
#Id
#Field
private String id;
#Field
public String origin_url;
#Field
public String[] predominantColor;
#Field
public double predominantColor_hue;
If I want to get all the "Imagen" where predominantColor_hue is near of the value I enter, how can I make a customized query for that? Because I just tried to use the
public interface ImagenRepository extends SolrCrudRepository<Imagen, String> {
Imagen[] findByPredominantColor_hue(double predominantColor_hue);
}
Also tried this
Imagen[] findByPredominantColor_hueIsLessThanAndPredominantColor_hueIsGreaterThan(double predominantColor_hue1, double predominantColor_hue2);
but I get this error:
No property hue found for type String! Traversed path: Imagen.predominantColor.
Maybe if I can make a custom query I can say to Solr that I want the Imagen which have a predominantColor_hue close to the one I want to compare. Maybe +5 and -5. But, how can I make that query? Already googled a lot and nothing found. Thanks and SORRY for my English!

Couple of suggestions,
Rename your predominantColor_hue field to predominantColorHue, because _ has a special meaning in spring-data queries.
Your Query should be like this
List<Imagen> findByPredominantColorHueGreaterThanAndPredominantColorHueLessThan(double predominantColor_hue1, double predominantColor_hue2);
If you want to get values near x, Now you can use this method like this
findByPredominantColorHueGreaterThanAndPredominantColorHueLessThan(x-5, x+5)

Related

How to group by max value and get full entities from MongoDB in Spring Boot?

I am new to MongoDB and have trouble. I would be very grateful if someone could help me with it.
I have the entity like:
class FileRecord {
private ObjectId id;
private String fileId;
private EnumStatus status;
private Long userId;
private Integer year;
etc.
> }
A file can have many records but only one in the year.
I need to get all the last documents by criteria.
I don't understand how to make it right in Spring, but in the mongo query too if to be honest)
I understand how to make criteria for it:
var match = match(Criteria.where("userId").in(userIds).andOperator(Criteria.where("status").in(EnumStatus.availableStatues())));
And group by max:
var group = group("fileId", "year").max("year").as("max_year");
But how to make it to query in one that will return for me Colletion<FileRecord> after aggregation?
If I try it make it this way:
var aggregation = newAggregation(filter, group);
AggregationResults<FileRecord> aggregateResult =
mongoOperations.aggregate(aggregation, FileRecord.class, FileRecord.class);
Collection<FileRecord> records = aggregateResult.getMappedResults()
I get an exception:
readObjectId can only be called when CurrentBSONType is OBJECT_ID, not when CurrentBSONType is DOCUMENT.;
If someone has an idea I'm interested
Thank you in advance
I found the answer)
var group = group("fileId", "year").max("year").as("max_year").first("_id").as("enityId");
I needed to create the projection and after again make request to the DB and get the data that I needed by id. I don't have many of them, so the solution worked for me. But, as I understand, you can add a lot "first", and add the fields you need. And get all by one request

#Query JpaRepository, querying decimal(19,4) becomes null when mapped to DTO BigDecimal or Long

Sorry, this is my first time posting so forgive me for my formatting and details:
I am having trouble with a #Query via JpaRepository
#Repository
public interface MonthlyBillingFeesRepository extends JpaRepository<MonthlyBillingFeesEntity, String> {
#Query(value = "SELECT new com.moo.operations.backend.dto.MonthlyAggregatedBillingFeesDto(" +
"SUM(m.customMooTotalBillingFeesSummary698721), " +
"m.entryDate) " +
"FROM " +
"MonthlyBillingFeesEntity m GROUP BY m.entryDate")
public List<MonthlyAggregatedBillingFeesDto> getAllBillingFeesByMonth();
the DTO:
public class MonthlyAggregatedBillingFeesDto {
private Long customMooTotalBillingFeesSummary698721;
#Type(type="timestamp")
private Date entryDate;
public MonthlyAggregatedBillingFeesDto(Long customMooTotalBillingFeesSummary698721, Date entryDate) {
this.customMooTotalBillingFeesSummary698721 = customMooTotalBillingFeesSummary698721;
this.entryDate = entryDate;
//getters setters
It works without a problem when I put the query directly into SQL. Also when I query via postman, it does return the entry dates properly, just not the Decimal values. I am not sure where the breakdown is. I have tried to use nativeQuery as well, and nothing works.
Ok thank you all, so I actually figured it out. Basically my column names that started with underscore _ really was causing issues with the hibernate naming strategy. No matter what I did, it wouldn't query the right column name. I had to change the names of the columns to camelcase and used:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
in the applications.properties file.

Getting empty result from the #Query in Hibernate

I am using Hibernate to execute my query, in admin panel i am getting correct result but while using in Hibernate it is not giving any result.
Dao layer -
#Query("select new com.eventila.pms.entity.ReferenceLead(projectId,count(lm)) from LeadMaster lm where lm.vendorId= ?1 and lm.source = 'share' group by lm.projectId")
List<ReferenceLead> getReferenceByUser(String userId);
Pojo -
#lombok.Data
#JsonInclude(JsonInclude.Include.NON_NULL)
public class ReferenceLead {
String projectId;
Long referenceLead;
Long count;
protected ReferenceLead(){}
public ReferenceLead(String projectId,Long count) {
this.projectId=projectId;
this.count=count;
}
}
After executing this i am getting a empty list.
Please help me out.
In your select query return the fields without calling new constructor:
#Query("select projectId, count(lm) from LeadMaster lm where lm.vendorId = ?1 and lm.source = 'share' group by lm.projectId")
List<ReferenceLead> getReferenceByUser(String userId);
Hibernate will instantiate the object using these fields. Also, add #Entity annotation to your ReferenceLead class.
'source' is the keyword in SQL.
It is a keyword used in MERGE. i.e. WHEN NOT MATCHED BY SOURCE.
The word MATCHED also exhibits the same behaviour in that it gets highlighted grey in the editor.
Neither of these are reserved keywords though so if used as an identifier they do not need to be delimited (unless you find the syntax highlighting distracting).

How to add search score of a document while converting solr search response to POJO using solrj

I am using SolrJ to interact with Solr instance. I simply want to get search score of each document returned by Solr for a particular search query. If I add a score field in my POJO with #Field annotation it works totally fine while retrieving documents. When I try to index something through the same POJO, Solr returns an error saying unknown field "score", as I do not have any field named "score" in my Solr schema. But, if I add a field named "score" in my Solr schema it starts returning the default value of score instead of search score. Please suggest me how to solve this problem. I do not want to iterate through all the documents one by one and add the score to POJO. I am performing following steps :
public void getSolrResult(String query) {
SolrQuery query = new SolrQuery();
query.set("q", query);
query.set("fl", "*, score");
QueryResponse queryResponse = solrjClient.query(query);
solrResult = queryResponse.getBeans(PojoSolr.class);
}
Class PojoSolr {
//Other fields
#Field("score")
private float searchScore;
public float getSearchScore(){
return searchScore;
}
public void setSearchScore(float score) {
this.searchScore = score;
}
}
I solved a similar problem like this using inheritance.
Simply move the score field down to a sub-class. Use the base class for indexing and the sub-class for querying.
class PojoSolr {
//Other fields
}
class PojoSolrOutput extends PojoSolr {
#Field("score")
private float searchScore;
}
Note that there are also use cases for the other way round, e.g. fields that are not stored and can thus not be retrieved, but must be indexed.
In this case another sub-class PojoSolrInput containing these fields makes sense.
Hope this helps.
My 30-minutes search on this topic lead me only to this SO post and:
http://lucene.472066.n3.nabble.com/How-to-get-the-score-in-the-result-td493812.html
http://lucene.472066.n3.nabble.com/Scoring-using-POJO-SolrJ-td3235016.html
In the second it's suggested to remove the #Field annotation from score, but it does not work. In both places no valid solution has been proposed.
So I came up with the solution of cycling on the "raw" results, binding them as getBeans does, and adding the score:
SolrDocumentList sdl = response.getResults();
List<T> documents = new LinkedList<>();
for (SolrDocument sd : sdl) {
#SuppressWarnings("unchecked")
T sb = (T) getClient().getBinder().getBean(<T class>, sd);
sb.setScore((Float) sd.get("score"));
documents.add(sb);
}

Persist HashMap in ORMLite

Im using ORMLite in my Android app. I need to persist this class, which has a HashMap. What is a good way of persisting it? Its my first time trying to persist a HashMap, also first time with ORMLite so any advice would be greatly appreciated!
*Edit*
If that makes any difference, the Exercise class is simply a String (that also works as id in the database), and the Set class has an int id (which is also id in database), int weight and int reps.
#DatabaseTable
public class Workout {
#DatabaseField(generatedId = true)
int id;
#DatabaseField(canBeNull = false)
Date created;
/*
* The hashmap needs to be persisted somehow
*/
HashMap<Exercise, ArrayList<Set>> workoutMap;
public Workout() {
}
public Workout(HashMap<Exercise, ArrayList<Set>> workoutMap, Date created){
this.workoutMap = workoutMap;
this.created = created;
}
public void addExercise(Exercise e, ArrayList<Set> setList) {
workoutMap.put(e, setList);
}
...
}
Wow. Persisting a HashMap whose value is a List of Sets. Impressive.
So in ORMLite you can persist any Serializable field. Here's the documentation about the type and how you have to configure it:
http://ormlite.com/docs/serializable
So your field would look something like:
#DatabaseField(dataType = DataType.SERIALIZABLE)
Map<Exercise, List<Set>> workoutMap;
Please note that if the map is at all large then this will most likely not be very performant. Also, your Exercise class (and the List and Set classes) need to implement Serializable.
If you need to search this map, you might consider storing the values in the Set in another table in which case you might want to take a look at how ORMLite persists "foreign objects".

Categories