How to make a custom sorting query in spring boot for a mongo db repository? - spring

I want to put this query with #Query annotation in my repository.
This is the query:
`db.report.find({'company' : 'Random'}).sort( { 'reportDate' : -1} ).limit(1)`
Which is the best way to implement custom queries with #Query annotations or to use MongoTemplate ?

Using Mongo Template.
Criteria find = Criteria.where("company").is("Random");
Query query = new Query().addCriteria(find).with(new Sort(Sort.Direction.DESC, "reportDate"));
BasicDBObject result = mongoOperations.findOne(query, BasicDBObject.class, "collection_name");
Using Mongo Repository
Report findTopByCompanyOrderByReportDateDesc(String company)

Note that in the new version of Springboot(v2.2.5), the correct method is sort.by().
like this:
Query query = new Query().addCriteria(find).with(Sort.by(Sort.Direction.DESC, "reportDate"));

Related

How can I write a custom query with spring in mongo?

I'm trying to make a query and fetch data over mongodb with Spring. But I don't know mongo and spring very well. I have these fields in my table. How can I write a custom query with this query in SQL? I mean give the qp value of the record whose id is this. How can I write this please help..
SELECT qp
FROM tableName
WHERE id = request.getId();
my custom query method is it true?
public Object findQueryParams(ProcessInfo processInfo ){
Query query = Query.query(Criteria.where("id").is(processInfo .getId()).is(processInfo .getQueryParams()));
return query;
}

How to create a composite index programmatically in spring Mongo data in Spring or spring boot?

How to create a MongoDB composite index with Spring Data programmatically in Java?
Using MongoTemplate I can create an index like that:
mongoTemplate.indexOps("collectionName").ensureIndex(new Index().on("fieldName", Sort.Direction.DESC).
Is there a way to create a composite key?
I saw that there is the class CompoundIndexDefinition that, by its name seems to be doing that, but I could not get it to work.
You can create compound indexes on any collection using Spring Data programmatically in Java as below:
// Compound indexes on the fields: fieldOne & fieldTwo
// db.groups.createIndex({fieldOne:1, fieldTwo:1})
IndexDefinition index =
new CompoundIndexDefinition(new Document().append("fieldOne", 1).append("fieldTwo", 1));
mongoTemplate.indexOps(CollectionName.class).ensureIndex(index);
The above example will create same index as on mongo shell:
db.groups.createIndex({fieldOne:1, fieldTwo:1})
With Spring Data, you can create index programmatically using MongoTemplate or MongoOperations
mongoTemplate.indexOps(CollectionName.class)
.ensureIndex(new Index().on("fieldOne", Sort.Direction.DESC)
.on("fieldTwo", Sort.Direction.ASC));
mongoOperations.indexOps(CollectionName.class)
.ensureIndex(new Index().on("fieldOne", Sort.Direction.DESC)
.on("fieldTwo", Sort.Direction.ASC));
I think this is the more appropriate approach.
#CompoundIndexes({
#CompoundIndex(name = "customIndex", def = "{'fieldOne' : 1, 'fieldTwo': 1}")
})
public class Entity {}
In spring boot JPA Mongo repository.

Convert ObjectId to String in Spring Data

How can I reference two mongodb collections using spring data while the localField is of type ObjectId and foreignField is of type String?
ProjectionOperation convertId=Aggregation.project().and("_id").as("agentId");
LookupOperation activityOperation = LookupOperation.newLookup().
from("activity").
localField("agentId").
foreignField("agent_id").
as("activities");
Aggregation aggregation = Aggregation.newAggregation(convertId,activityOperation);
return mongoTemplate.aggregate(aggregation, "agents", AgentDTO.class).getMappedResults()
However, this doesn't return any records because of the type issue. Is it possible to implement $toString or $convert in ProjectionOperation? or what other options are there?
I was able to solve it by writing native mongodb aggregation operation in java code as described in MongoDB $aggregate $push multiple fields in Java Spring Data
After implementing this solution I was able to add native $addfields as follows:
AggregationOperation addField=new GenericAggregationOperation("$addFields","{ \"agId\": { \"$toString\": \"$_id\" }}");

How to get top results using specifications in spring data jpa?

I am quite new to spring data jpa. I am trying to use specifications while querying database. My question is using crudrepository we can method like :
findTopByUsernameOrderByUpdatedAtDesc(String username);
How can I achieve the same using specifications? I can do basic things like and or in specifications, but not very robust like we can do with criteria etc.
Specification<CustomClass> spec = Specifications.where(specification).and(username);
List<CustomClass> list = findAll(spec);
This was done as follows :
Pageable pageable = new PageRequest(0, 1, Sort.Direction.DESC, "username");
Page oneElementPage = repository.findAll(spec, pageable);
This will sort the data on username column in descending direction and return first result.
You can't express this in a Specification directly. But you can use a Pageable for this:
Page oneElementPage = repository.findAll(spec, new PageRequest(0, 1));
Gives you a Page with a single element.

SpringData JPA Repository Method Query with a like?

In Spring-data JPA, is there anyway to create a method query that is essentially searches by like??
I have the following method query
public MakeModel findByModelIgnoreCase(String model);
What I really want is a like expression. Do I need to just create a Criteria or a #Query annotation? Am I asking too much?
//Stupid example of what I want to be able to do
public MakeModel findByFuzzyModelIgnoreCase(String model);
Really I guess at the heart of it, I want to do a table search. I'm using Hibernate underneath Spring Data so I guess I could use some search api like Hibernate Search. I'm open to recommendations here.
If you don't want add "%" manually, you can use the following query methods:
MakeModel findByModelStartingWithIgnoreCase(String model); //SQL => LIKE 'model%'
MakeModel findByModelEndingWithIgnoreCase(String model); //SQL => LIKE '%model'
MakeModel findByModelContainingIgnoreCase(String model); //SQL => LIKE '%model%'
Like is supported too:
MakeModel findByModelLikeIgnoreCase(String model);
When you call the method use the follwing:
Add "%" at the start to say that it doesn't matter to be a strict start match ,
the same at the end, or you can use one of them it depends on the like you want.
MakeModel makeModel = findByModelLikeIgnoreCase("%"+model+"%");
if your make model Is test and the string to compare to is "%"+model+"%" then :
es is a match , T is a match , test is a match
the string to compare to is model+"%":
te is a match , es is not .

Resources