Spring Data Mongodb POJO mapping - mongodb

I know that Spring Data MongoDB is a POJO centric model for interacting with a MongoDB DBCollection. But in my case the POJO mapping is somewhat irrelevant.For example the JSON string that I need to store as a single document in a collection is as follows
columns:[
{
name:"xyz"
age:12
},
{
name:"abc"
age:34
},
{
name:"pqr"
age:76
}
]
What can be the equivalent POJO mapping in this case?

I think you can achieve it through this mapping (If I understood your question correctly):
class Person {
String name;
int age;
}
class Outer {
#Field("columns")
List<Person> persons;
}

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.

Using the ID value object of an aggregate for persistance with MongoDB

A classic DDD rule is that aggregates should reference each other via their ID, and that the ID of an aggregate should be a value object. So something like this (in Java):
class MyAggregate {
private MyAggregateId id;
private String someOtherField;
...
}
class MyAggregateId {
private UUID id;
}
How can i make MongoDB use MyAggregateId instead of the autogenerated ObjectID? Is that possible?
Bonus points if the answer involves doing this with spring-boot, where i hoped i could just declare public interface MyAggregateRepository extends MongoRepository<MyAggregate, MyAggregateId> {} but that does not seem to work.

MongoDB - FindById is not working and giving null

I am using Spring Boot(V2.2.2.RELEASE) + Spring Data Mongo Example. In this example, I've records like below
{
"_id" : ObjectId("5cb825e566135255e0bf38a4"),
"firstName" : "John",
"lastName": "Doe"
}
My Repository
#Repository
public interface EmployeeRepository extends CrudRepository<Employee, ObjectId>{
Employee findById(String id);
}
Code
Employee findById = employeeRepository.findById("5cb825e566135255e0bf38a4");
System.out.println(findById);
Even below code not working
Query query = new Query(Criteria.where("id").is(new ObjectId("5cb825e566135255e0bf38a4")));
List<Employee> find = mongoTemplate.find(query, Employee.class);
Seems there might be two issues
ObjectId should be used
employeeRepository.findById(new ObjectId("5cb825e566135255e0bf38a4"))
ID field goes with underscore
new Query(Criteria.where("_id").is(new ObjectId("5cb825e566135255e0bf38a4")))
I'm not a Java guy, so might miss smth, but at least give it a try :)
Using the input document with _id: ObjectId("5cb825e566135255e0bf38a4") you can use either of the approaches. Assuming there is the document in the employee collection you can query by the _id's string value.
public class Employee {
#Id
private String id;
private String name;
// constructors (with and with arguments)
// get methods
// override toString()
}
// Spring-data app using MongoTemplate
MongoOperations mongoOps = new MongoTemplate(MongoClients.create(), "test");
Query query = new Query(where("id").is("5cb825e566135255e0bf38a4"));
Employee emp = mongoOps.findOne(query, Employee.class);
-or-
MongoRepository
interface extends CrudRepository and exposes the capabilities of the
underlying persistence technology in addition to the generic
persistence technology-agnostic interfaces such as CrudRepository.
#Repository
public interface EmployeeRepository extends MongoRepository<Employee, String> {
#Query("{ 'id' : ?0 }")
Optional<Employee> findById(String id);
}
// Spring-data app using the Repository
Optional<Employee> empOpt = employeeRepository.findById("5cb825e566135255e0bf38a4");
if (empOpt.isPresent()) {
System.out.println(empOpt.get());
}
else {
System.out.println("Employee not found!");
}
I too faced the issue. Interestingly things are working fine with version 2.1.7RELEASE
<documentRepository>.findById(<StringID>) treats as String Id in 2.2.2RELEASE
while 2.1.7RELEASE transforms it to ObjectId and hence the find query works.

Mapping a Collection without using DBRef (Spring Data MongoDB)

I've been reading a lot that the use of DBRef for Collection Mapping in Spring Data/MongoDB is discouraged. So, how can I implement a mapping that stores an array of ObjectId taken from those objects inside the students collection?
Assuming that I have the following POJO model:
#Document (collection = "courses")
public class Course {
#Id
private String id;
private String name;
private List<Student> students = new LinkedList<Student>();
//.. constructors, getters and setters ..
}
public interface CourseRepository extends MongoRepository<Course, String> { }
The result should be something like this:
courses
{
_id : ObjectId("foo"),
_class: "model.Course",
name: "MongoDB for Dummies",
students: [ ObjectId("foo2"), ObjectId("foo3"), ... ]
}
Instead of this:
courses
{
_id : ObjectId("foo"),
_class: "model.Course",
name: "MongoDB for Dummies",
students: [
DBRef("student", ObjectId("foo2")),
DBRef("student", ObjectId("foo3"))
]
}
Thanks!
You might wanna try the obvious and change students to a List<ObjectId>. ;)

javaee 6 rest api named query result

I have a simple JEE6 rest class that gets the data from db2. I am using Jackson in ApplicationConfig class to convert the entity objects to json. It converts with the field names as the key and the value as the right hand value. So for example:
Class Entity {
String name;
String address;
}
converts to
{name:"hello", address:"world"}
The service is as follows:
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
Now I want to only return the name in json format. So I created a named query as follows in the entity class:
#NamedQuery(name = "justGetName", query = "SELECT a.name FROM Applications a")
And the service changed to
public List<T> findAll() {
return getEntityManager().createNamedQuery("justGetName").getResultList();
}
This returns the following array:
[{"first","second","third"}]
But I want to get back:
[{name:"first",name:"second",name:"third"}]
How do I write the named query so that the class field names are added to the json structure? Thank you.
You querying a list of strings from your database and this is what the service returns.
Their are multiple ways to achieve your goal.
Pure JPA
Using #JsonIgnore to tell Jackson not to serialize an attribute
class Application {
String name;
#JsonIgnore
String address;
}
Create a new Entity class that only contains the attributes you would like to share
class ApplicationName {
String name;
}
Alternatively you could introduce a separate class that only contains the attributes you would like to share and convert the results from the query into this class and return than the list of this converted values.