Nested MongoDB query syntax not working in Springboot - mongodb

I have 3 classes:
` ClassA{
private String name;
private List<ClassB> classb;
}
ClassB{
private String name;
private List<ClassC> classc;
}
ClassC{
private String name;
private String email;
}`
Now, my situation is based on ClassC's name , I have to display the email.
Here, I write a mongo query in my repository layer(in spring boot) as:
#Query(value="{'classb.classc.name':?0}",fields="{'classb.classc.email':1}")
But this mongo Query does not work properly, it displays every email from classC without matching the selection.
I am not sure where I am wrong. Please guide me through how to work out in such nested situation.
Thanks

Related

How to delete a field in all documents of mongodb collection using MongoRepositoty #Query

I have a collection:
public class Person {
private String name;
private Integer age;
}
I want to delete field age in all the documents. So the schema gonna look like that:
public class Person {
private String name;
}
I'm using MongoRepositoty and I've been trying to write this method:
#Repository
public interface PersonRepository extends MongoRepository<Person, String> {
#Query("{$updateMany: [ {}, { $unset: {'age': ''} }]}")
void deleteAgeField();
}
I tried different brackets and quotes, but it all ends up with errors. What's wrong with my syntax? I see it differs from how we write queries in mongo console. For instance, round brackets and double quotes are not allowed here.
You could use simply
#Query(value = "{}", delete = true)
void deleteAgeField();
A solution I've found is simply to set the field to null:
repository.findAll().forEach(
person -> {
person.setAge(null);
repository.save(person);
});
As Mongo is not relational DB, it contains documents not tables. It has json presentation of objects, and when a field=null, it disappears. Maybe my explanation is a bit twisted, please correct me if I'm wrong.

How to get last record in spring mongo?

I have a transaction class which stores the each transaction of a customer,Following are the fields in this class.
class Transaction{
#Id
private String id;
private Date date;
private String customerId;
private double openBalance;
private double transctionAmount;
private double finalAmount;
}
I need to fetch only the last inserted record of a customer (let say for customerId = cust123).
I defined following function in repository.
public interface TranscationRepository extends MongoRepository<Transaction, String> {
Optional<Transaction> findTopByCustomerIdOrderByIdDesc(String id);
}
This method giving last entry not by customerId but overall. I tried few modifications to it but did not get success.
I know I can findAllByCustomer but I don't want to pull huge list of transaction which is of no use in this use case. What is correct signature in spring mongo to get last inserted record by a field? I am ok to use custom #Query also.
Thank you.

How can I get data from #DBRef document using #Query -> Spring data mongo

I need help to get the data from another document I have the following class.
#Data
#Document(collection = "tmVersion")
public class TmVersion {
#Id
private String id;
private String cVrVersionId;
#DBRef
private TaApplicationVersion taApplicationVersion;
}
and
#Data
#Document(collection = "taApplicationVersion")
public class TaApplicationVersion {
#Id
private String id;
private String dVrAppName;
private String dVrAppCode;
}
This is my repository in which I map what I want to be shown but in taApplicationVersion I need to show all this object also how is it done?
#Query(value="{}", fields="{'cVrVersionId': 1, 'taApplicationVersion.dVrAppName': 2,
'dVrVersionNumber': 3}")
Page<TmVersion> getAllVersionWithOutFile(Pageable pageable)
Couple of things to mention here.
If you want this kind of join between tables, then you need to rethink your choice of Mongodb as database. No Sql Databases thrive on the fact that there is very less coupling between tables(collections). So if you are using #DBRef, it negates that. Mongodb themselves do not recommend using #DBRef.
This cannot be achieved with the method like you have in the repository. You need to use Projections. Here is the documentation for that.
Create a Porjection interface like this. Here you can control which fields you need to include in the Main class(TmVersion)
#ProjectedPayload
public interface TmVersionProjection {
#Value("#{#taApplicationVersionRepository.findById(target.taApplicationVersion.id)}")
public TaApplicationVersion getTaApplicationVersion();
public String getId();
public String getcVrVersionId();
}
Change the TmVersionRepository like this
public interface TmVersionRepository extends MongoRepository<TmVersion, String> {
#Query(value="{}")
Page<TmVersionProjection> getAllVersionWithOutFile(Pageable pageable);
}
Create a new Repository for TaApplicationVersion. You can add #Query on top of this method and control which fields from subclass needs to be returned.
public interface TaApplicationVersionRepository extends MongoRepository<TaApplicationVersion, String> {
TaApplicationVersion findById(String id);
}

Spring Data update mongodb Document with DBRF lazy attribute

I want to update a MongoDB document containing a dbrf lazy attribute using spring data.
First of all, I load the existing document, I change the attributes I want and after that, I call #Repository save method, but when I check the document in MongoDB the dbrf lazy attribute is null.
I tried to load the attribute before by calling getAttribute, but that doesn't fix the problem.
Someone could help me?
Thanks
I have the Collection below:
#Data
#Document(collection = "calendriers")
public class CalendrierEntity {
#Id
#AutoGenerate(SequanceKey.CALENDRIER)
private Long id;
#NotNul
private String label;
#NotNull
private HorairesEntity horairesEntity;
#DBRef(lazy = true)
#CascadeSave
#Getter(AccessLevel.NONE)
private List<AbsenceEntity> absenceEntities;
}
and the repository bellow :
#Repository
public interface AbsenceRepository extends MongoRepository<CalendrierEntity, Long> {
AbsenceEntity findById(Long enfantId, LocalDate localDate);
}
I have calendrier document with Id 1L and want to update his label.
The calendrier document have allready a list of Absences.
this my code to update the label.
#Transactional
public void updateLabelCalendrier(Long id, String label){
CalendrierEntity calendrier = calenderRepository.findById(1L);
calendrier.setLabel(label);
calenderRepository.save(calendrier);
}
but when i check data in mongodb, i have the new label but my list of absences became null.

Play 2.0 Morphia design pattern with mongodb

This is my first time using MongoDb and morphia and I am pretty new to databases in general. I am wondering how I should organize my code with morphia. I was looking into using a DAO like it says on the morphia documentation, but the way they seem to be doing it, I would have to create a DAO for each model object that I have. I liked play's methodology of basically giving Model objects the ability to save themselves but I only have vague notions of what is going on under the hood here, so I am not sure how to achieve this with morphia, or if it is even desirable to do so. The code I have so far looks like this for the skeleton of a User model.
#Entity("user")
public class User extends BasicDAO<User, ObjectId>{
#Id ObjectId id;
public String firstName;
public String lastName;
public String email;
#Indexed public String username;
public String password;
public User(Mongo mongo, Morphia morphia){
super(mongo, morphia, "UserDAO");
}
public User(){
this(DBFactory.getMongo(), DBFactory.getMorphia());
}
public void save(){
ds.save(this);
}
public static User findByUsername(String uname){
return DBFactory.getDatastore().find(User.class, "username =", uname).get();
}
public static boolean authenticate(String uname, String pword){
User user = DBFactory.getDatastore().createQuery(User.class).filter("username", uname).filter("password", pword).get();
if(user == null)
return false;
else
return true;
}
}
It is currently throwing a StackOverflowException, and I am not sure why, but is this a reasonable pattern to try to accomplish?
Also the DBFactory basically just exists to maintain the singleton mongodb connection.
Play 2.0 have a module for working with MongoDb I think You should give it a try
https://github.com/vznet/play-mongo-jackson-mapper#readme
I started using Marphia with play framework 2.x. In my opinion, it is more sophisticated than the jackson mapper. I followed this example to install marphia plugin: https://github.com/czihong/playMongoDemo