Spring mongo how to retrieve data but newest date first - spring

How to I set my data when I retrieve it that the newest date will be first .At the moment when I retrieve it ist is newest date last. Tried order by but not managing
public class Notifications {
#Id
private String id;
private String notificationMsg;
private Date createdDate = new Date();
//Contructor
//Getter and Setter

You can use this chunk of code, I hope it'll solve your problem <3
Query query = new Query();
query.with(new Sort(new Order(Direction.ASC, "createdDate").ignoreCase());
return mongoTemplate.find(query, Notifications.class);

If you are using spring-data with a #Repository annotation you can do this:
List<Notifications> findAllByOrderByCreateDateAsc();

Related

Elastic search with Spring Data for Reactive Repository - Deleting based on nested attributes

I am using Spring data for Elastic Search and am using the ReactiveCrudRepository for stuff like finding and deleting. I noticed that with attributes that are in root and are simple objects, the deletion works (deleteByAttributeName). However if I have nested objects then it does not work.
Here's my entities
Book
#Data
#TypeAlias("book")
#Document(indexName = "book")
public class EsBook{
#Field(type = FieldType.Long)
private Long id;
#Field(type = FieldType.Nested)
private EsStats stats;
#Field(type = FieldType.Date, format = DateFormat.date)
private LocalDate publishDate;
}
Stats
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode
public class EsStats{
#Field(type = FieldType.Double)
private Double averageRating;
#Field(type = FieldType.Integer)
private Double totalRatings;
#Field(type = FieldType.Keyword)
private String category; //this can be null
}
Here is what I have tried and is working and not working
I used ReactiveCrudRepository to delete documents in index. For all the regular fields on Book Level like id or with id and publishDate deletion works perfectly. As soon as I use embedded object like Stats, it stops working. I see the documents and the stats that I am sending match atleast visually but never finds or deletes them.
I tried to use EqualsAndHashcode in the Stats assuming maybe iternally somehow does not consider equal for some reason. I also tried changing double data type to int, because on looking at the elastic search document, I see that average review if whole number like 3 is save as 3 but when we send it from Java, i see in the debug 3 being shown as 3.0, so I was doubting if that is the case, but does not seem so. Even changing the datatype to int deletion does not work.
public interface ReactiveBookRepository extends ReactiveCrudRepository<EsBook, String> {
Mono<Void> deleteById(long id); //working
Mono<Void> deleteByIdAndPublishDate(long id, LocalDate publishDate); //Nor working
Mono<Void> deleteByIdAndStats(long id, LocalDate startDate);
}
Any help will be appreciated
Have you verified that your Elasticsearch index mapping matches your Spring Data annotations?
Verify that the index mapping defines the stats field as a nested field type.
If not, then try changing your Spring annotation to:
#Field(type = FieldType.Object)
private EsStats stats;

Spring Mongodb aggregation doesn't work with DBRef

I have an aggregation which doesn't work in mongodb and spring boot. I would be grateful if anyone could help me.
Here is my ExplainDoc class:
#Document(collection = "ExplainDoc")
public class ExplainDoc{
#Id
private String id;
#TextIndexed(weight=3)
private String product_in_brief;
private Product product;
#TextScore
private Float textScore; }
And here is my other class:
#Document(collection = "product")
public class Product{
#Id
private String id;
private String category;
}
What I want to do is to make a text search and find all ExplainDocs which have the given text in their product_in_brief PROVIDED THAT their product has a specific category.
In my search repository, I have an aggregation like the following:
public List<MyAggrResults> searchBriefExplanations(String text, String category){
MatchOperation matchRegion = Aggregation.match(Criteria.where("product.category").is(category));
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny(text);
MatchOperation match = Aggregation.match(criteria);
GroupOperation group = Aggregation.group("product.category").push("$$ROOT").as("myresults").sum("textScore").as("score");
ProjectionOperation project = Aggregation.project("product_in_brief", "product").andExpression("{$meta: \"textScore\"}").as("textScore");
}
The code works now. However, I see it is so expensive to have the product object always as a nested document. How should I change the code if I want to use the product object as #DBRef? When I add the #DBRef, the code doesn't work anymore. I think the reason is that the product.category is not recognized anymore.
I hope somebody can help me.
There is nothing special about DBRef that magically makes it efficient. It is simply a label for the combination of collection name and an id. You still need to use aggregation pipeline to query data that uses DBRef in the same way you'd query if you didn't use DBRef.

Spring Boot + Webflux + Reactive MongoDB - get document by property Id

I'd like to find all Offer documents by Offer.ProductProperties.brand:
#Document(collection = "offers")
public class Offer {
#Id
private String id;
#NotNull
#DBRef
private ProductProperties properties;
ProductProperties:
#Document(collection = "product_properties")
public class ProductProperties {
#Id
private String id;
#NotNull
#NotEmpty
private String brand;
Service:
Flux<ProductProperties> all = productPropertiesRepository.findAllByBrand(brand);
List<String> productPropIds = all.toStream()
.map(ProductProperties::getId)
.collect(Collectors.toList());
Flux<Offer> byProperties = offerRepository.findAllByProperties_Id(productPropIds);
But unfortunately byProperties is empty. Why?
My repository:
public interface OfferRepository extends ReactiveMongoRepository<Offer, String> {
Flux<Offer> findAllByProperties_Id(List<String> productPropertiesIds);
}
How to find all Offers by ProductProperties.brand?
Thanks!
After reading some documentation found out that You cannot query with #DBRef. Hence the message
Invalid path reference properties.brand! Associations can only be
pointed to directly or via their id property
If you remove DBRef from the field, you should be able to query by findAllByProperties_BrandAndProperties_Capacity.
So the only ways is how you are doing. i.e. Fetch id's and query by id.
As I said in the comment, the reason it is not working is because return type of findAllByProperties_Id is a Flux. So unless u execute a terminal operation, you wont have any result. Try
byProperties.collectList().block()

Why does a combination of two JPQL queries that work separately do not work when combined?

In a spring-boot project useing hibernate I want to create a query that returns all the actions that have dates between dates and ByMethodPaymentId.
The entity class:
#Entity
public class Action {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#JsonFormat(pattern = "yyyy-MM-dd")
private Date date;
#ManyToOne
#JsonIgnore
#Valid
private MethodPayment methodPayment;
//constructor....getter... setter...
this the repository to action:
#Repository
public interface ActionRepository extends JpaRepository<Action, Long>{
// Dont works
Collection<Action> findByMethodPaymentIdAndByDateBetween(long methodPaymentId,Date startDate, Date endDate );
// works
Collection<Action> findByMethodPaymentId(long methodPaymentId);
// works
Collection<Action> findByDateBetween(Date startDate, Date endDate);
Why do the last two queries work but the first one that is a combination of both does not work?
You don't have to mention By again when using JPQL, so the method will be like
Collection<Action> findByMethodPaymentIdAndDateBetween(long methodPaymentId,Date startDate, Date endDate );
Try this.
Just Remove the By after And
Change
findByMethodPaymentIdAndByDateBetween()
To
findByMethodPaymentIdAndDateBetween()
Final Query
Collection<Action> findByMethodPaymentIdAndDateBetween(long methodPaymentId,Date startDate, Date endDate );
Multiple And/OR
findByFirstParameterAndSecondeParameterORThirdParameter(...)

Spring-Mongo : mapping mongo document field/s to BasicDBObject/Map of BasicDBObject of an Entity

I have an entity ProjectCycle mapped to mongo DB collection ProjectCycle. I am trying to retrieve 2 fields, _id and Status. I am able to retrieve both like the following
#Document(collection="ProjectCycle")
public class ProjectCycle {
#Id
private String id;
#Field("Status")
private String status;
//getters and setters
}
Application.java
Query query = new Query();
query.fields().include("Status");
Criteria criteria = new Criteria();
criteria.and("_id").is("1000");
query.addCriteria(criteria);
Iterable<ProjectCycle> objectList = mongoOperations.find(query, ProjectCycle.class);
for(ProjectCycle obj : objectList) {
System.out.println("_id "+obj.getId());
System.out.println("status "+obj.getStatus());
}
Output
_id 1000
status Approved
But, the problem is when i use an Entity with field private DBObject basicDbObject; instead of private String status; i am getting value as null instead of Approved
I have tried like the following
public class ProjectCycle {
#Id
private String id;
private DBObject basicDbObject;
//getter & setter
}
What I am trying to achieve is that, the collection 'ProjectCycle' is very large and creating a POJO corresponding to it is quiet difficult. Also I am only reading data from mongoDB. So creating the entire POJO is time wasting and tedious.
How I can achieve mapping between any field/fields from mongo Collection to entity?.
Will it be possible to create a Map<String, BasicDBObject> objectMap; to fields returned from query? I am using Spring-data-mongodb for the same.
Version details
Spring 4.0.7.RELEASE
spring-data-mongodb 1.7.2.RELEASE
Try mapping your query like below.
Iterable<BasicDBObject> objectList = mongoOperations.find(query, BasicDBObject.class, collectionname);
for(BasicDBObject obj : objectList) {
System.out.println("_id "+obj.get("id"));
System.out.println("status "+obj.get("status"));
}

Resources