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

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.

Related

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.

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);
}

How can i design a Model of a document contains more than one collection in Mongodb

I am novice in mongodb.
I have a mongodb and i have a table / document(Ex: sampleTable).
I know how to retrieve data from this single table.
I used below code to retrieve data and working fine.
#Document(collection="sampleTable")
public class sampleMapping {
private String id;
private String strClassName;
public sampleMapping () {}
public sampleMapping (String strClassName) {
super();
this.strClassName = strClassName;
}
public String getStrClassName() {
return strClassName;
}
public void setStrClassName(String strClassName) {
this.strClassName = strClassName;
}
}
But now, i wanted to retrieve data from more than one table. How can i do that?
Say, i need to retrieve table1 and table2.
How can i update the above code to get data from multiple collections?

Spring mongodb get ID of inserted item after Save

I am working with Spring MongoDb.
I create various entities using insert method:
http://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/MongoOperations.html#insert-java.lang.Object-
However, all methods return void. I need to return the ObjectId of the inserted document.
What is the best way to get it?
This is pretty interesting and thought I would share. I just figured out the solution for this with the help of BatScream comment above:
You would create an object and insert it into your MongoDB:
Animal animal = new Animal();
animal.setName(name);
animal.setCat(cat);
mongoTemplate.insert(animal);
Your animal class looks like this with getters and settings for all fields:
public class Animal {
#Id
#JsonProperty
private String id;
#JsonProperty
private String name;
#JsonProperty
private String cat;
public String getId() {
return id;
}
}
AFTER you have done the insert under mongoTemplate.insert(animal);, you can actually call the method animal.getId() and it will return back the ObjectId that was created.
I had the same problem with #AlanH that animal.getId() is null. And then I just realized my id field had been set as a final field with a wither method. So of course getId() is null since the id field is immutable and the wither method returns a new object with id.
if this is the case: use animal = template.insert(animal).

Using the $in operator through Morphia - doing it wrong?

I have the following Play Framework entity (using Morphia for persistence) as part of a generic blogging app:
#Entity
public class Comment extends Model {
...
#Reference
#Indexed
public SiteUser commenter;
public static List<Comment> getLastCommentsByUsers(final List<SiteUser> users) {
final Query<Comment> query ds().createQuery(Comment.class);
query.field(commenter).hasAnyOf(users);
return query.asList();
}
}
SiteUser:
#Entity(noClassnameStored=true)
public class SiteUser extends AbstractUser {
public String realName;
}
AbstractUser:
public class AbstractUser extends Model {
#Indexed(value= IndexDirection.DESC, unique = true)
public String emailAddress;
#Required
public String password;
}
The method getLastCommentsByUsers() is supposed to return all comments by the users in the users parameter, but I always get an empty List back. The reason that Commment is a separate collection is to be able to retrieve last X Comments by certain users across their associated Posts, which isn't possible if the Comment is embedded in the Post collection.
Is there something wrong with my query (should I be using something other than hasAnyOf), or is it a problem with the relationship mapping - should I be using ObjectId instead?
I use the in() method with a list or set and its working perfectly. Here's a snippet:
List<String> keywordList;
List<Product> products = Product.find().field("keywords").in(keywordList).asList();
This should work for collection of embedded or references too.
You should use List<Key<SiteUser>> to query:
public static List<Comment> getLastCommentsByUsers(final List<SiteUser> users) {
final Query<Comment> query ds().createQuery(Comment.class);
query.field(commenter).hasAnyOf(toKeys(users)); // convert to keys
return query.asList();
}
public static List<Key<SiteUser>> toKeys(List<SiteUser> users) {
List<Key<SiteUser>> keys = new ArrayList<Key<SiteUser>>();
for(SiteUser user: users) {
keys.add(ds().getMapper().getKey(user));
}
return keys;
}
Or you can just get the keys by:
List<Key<SiteUser>> keys = ds().createQuery(SiteUser.class).query().filter(...).asKeyList();