How to delete a nested embedded sub document using MongoTemplate - mongodb

Scenario
I have 1 Collection: Discussion
Discussion Collection contains 2 embedded Documents(one inside another)
Discussion contains reply, reply contains comment
I am using MongoTemplate in my Project (Spring with MongoDB)
My POJO Details:
Discussion
#Document(collection = "discussion")
public class Discussion {
private String discussion_id;
private String title;
private String description;
private Date discussion_time;
private String initiated_by;
private Set<String> topic_tags;
private int replies_count;
// List of Replies
private List<Reply> replies;
}
Reply
public class Reply {
private String reply_id;
private String replied_by;
private String reply_content;
private Date replied_date;
private float rating;
//List of Comments
private List<Comment> comments;
}
Comment
public class Comment {
private String comment_id;
private String commented_by;
private String comment_content;
private Date commented_date;
}
Hint
I can able to delete reply from Discussion Collection.Code as follows
public void deleteReply(String reply_id, String replied_by, String initiated_by) {
if (replied_by.equals(initiated_by)) {
Query query = new Query(Criteria.where("initiated_by").is(initiated_by));
query.fields().elemMatch("replies", Criteria.where("reply_id").is(reply_id));
Update update = new Update();
update.pull("replies", new BasicDBObject("reply_id", reply_id));
mongoTemplate.updateMulti(query, update, COLLECTION_NAME);
logger.info("deleted reply successfully ");
} else {
logger.info(" Unauthoriszed to delete ");
}
}
I want to delete a comment from Discussion Collection. can any one provide the solution.

Related

Spring MongoDB: Auditing one-to-many relation subdocument

I am currently working on a self-taught project, thus I am a beginner in MongoDB and I am struggling to audit a subdocument in an one-to-many relation. For some reason none of the new records inserted in this collection is being audited, although audit is working fine for all the other collections.
Below is the structure of the collections in my project:
User document is the main Document - auditing ok
Provider is an embedded subdocument in User (One-to-One) - auditing ok
Address is an embedded set of documents in Provider (One-to-Many) auditing fail
public class User extends Audit<String>{
#Id
private String id;
private String email;
private String firstName;
private String lastName;
private String salt;
private String password;
private String role;
private Boolean isVerified;
private String userTempCode;
private LocalDateTime deactivationDate;
private Provider provider; // This subdocument gets audited no problem
...
public class Provider extends Audit<ObjectId>{
private ObjectId id = new ObjectId();
private LocalDate dob;
private String phone;
private Double price;
private Object geoLocation;
private Set<WeekDays> days;
private Set<TimeRange> hours;
private Set<Address> addresses; // Here is where I am having trouble, the createdBy, createdDate and so on, are not working
private String userId;
private LocalDateTime deactivationDate;
private Set<Reviews> ratings;
....
public class Address extends Audit<ObjectId>{
#Id
private ObjectId id = new ObjectId();
private String street;
private String street2;
private String city;
private String province;
private String country;
private String postalCode;
...
//Below My Audit class inherited by all documents
#Data
public abstract class Audit<T> implements Persistable<T> {
#CreatedBy
private String createdBy;
#CreatedDate
private LocalDateTime createdDate;
#LastModifiedBy
private String lastModifiedBy;
#LastModifiedDate
private LocalDateTime lastModifiedDate;
#Version
public Integer version;
}
So, why is my Set< Address> not being audited whereas the other documents are ok, am I missing something here?
Thank you!

How to update few fields in mongodb by using MongoRepository?

I have a User POJO having fields:
#Id
private String _id;
private String phone;
private String email;
private String password;
private String userName;
private String dob;
private String gender;
private String city;
private String pincode;
private String status;
private String validUpto;
private List<String> userRole;
private String persona;
I saved all the fields in MongoDB (document).
Now I want to update only few fields like city, Pincode.
I also refer this question, but it is not giving the answer via MongoRepository.
is there any way we can update only few fields via MongoRepository instead of MongoTemplate.
The repository doesn't provide an 'update' operation only .save(object);
But you can update it by retrieving the Object from the repository, change the relevant fields. Afterwards, you save the updated object to the repository.
Which will get you the desired result of 'updating'.
Spring-boot/SpringRepository example.
#Autowired
UserRepository userRepository;
#Test
public void testUpdateUser() throws Exception {
User foundUser = userRepository.findById("1");
foundUser.setCity("Helsinki");
// foundUser.setOtherFields("new values");
userRepository.save(foundUser); // Will 'update' but it essentially replaces the entity in database
}

Spring data MongoDB match, lookup and projection to select only required field from looked-up document

I have below two Document structures. In the structure CRMContact.orgGroupId == OrganizationGroup.id. I would like to fetch all the CRMContact document that matches with sharedGroupIds and also select only a few fields from CRMContact and only OrganizationGroup.groupownername from OrganizationGroup and match/populate groupId (with only one field [groupownername] populated). I have used below custom implementation but didn't work.
I have included aggregarionsNotWorking which is not working and aggregarions returning entire OrganizationGroup populated. How to achieve this i.e. just to populate groupownername field, using spring data mongodb?
#Document(collection = "ww_crm_contact")
public class CRMContact{
#Id
protected String id;
private String displayName;
private String firstName;
private String middleName;
private String lastName;
private OrganizationGroup groupId; //Ignore //Modified field name orgGroupId
#Indexed(name = "CRMCONTACT_SHAREDGROUPID_IDX",background = true)
private List<String> sharedGroupIds = new LinkedList<>();
#Indexed(name = "CRMCONTACT_ORGGROUPID_IDX",background = true)
private String orgGroupId;
}
#Document(collection = "ww_organization_groups")
public class OrganizationGroup {
private static final long serialVersionUID = 600049975643062552L;
#Id
protected String id;
private String groupName;
private int riaId;
private Boolean isPrivate;
private String description;
private Boolean deleted;
#Transient
private int count;
private String groupownerid;
private String groupownername;
}
#Repository
public class CustomCRMContactDAO {
#Autowired
MongoTemplate mongoTemplate;
public List<CRMContact> getContactsPresentInGroup(List<ObjectId> objectIds){
LookupOperation lookupOperation = LookupOperation.newLookup().from("ww_organization_groups").localField("orgGroupId").foreignField("_id").as("groupId");
ProjectionOperation fields = project("firstName","lastName", "primaryId","displayName","groupId.groupownername");
Aggregation aggregarionsNotWorking = Aggregation.newAggregation(Aggregation.match(Criteria.where("sharedGroupIds").in(objectIds)),lookupOperation,unwind("groupId"),fields); //Not Working even if I change the field only to groupownername
Aggregation aggregarions = Aggregation.newAggregation(Aggregation.match(Criteria.where("sharedGroupIds").in(objectIds)),lookupOperation,fields); //
List<CRMContact> crmContacts = mongoTemplate.aggregate(aggregarions, "ww_crm_contact",CRMContact.class).getMappedResults();
return crmContacts;
}
}

MongoDB Aggregtation Pipleline using Spring Boot [duplicate]

I am using spring data Mongodb in my project and refer the below classes for my query on grouping the results:
Student class:
#Document(collection = "student")
public class Student {
#Id
private String id;
private String firstName;
private String lastName;
//other fields
//getters & setters
}
StudentResults (dto):
public class StudentResults {
private String firstName;
private List<String> studentIds; //I need List<Student> here
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public List<String> getStudentIds() {
return studentIds;
}
public void setStudentIds(List<String> studentIds) {
this.studentIds = studentIds;
}
}
StudentServiceImpl class:
public class StudentServiceImpl implements StudentService {
#Autowired
private MongoTemplate mongoTemplate;
public List<StudentResults> findStudentsGroupByFirstName() {
TypedAggregation<Student> studentAggregation =
Aggregation.newAggregation(Student.class,
Aggregation.group("firstName").
addToSet("id").as("studentIds"),
Aggregation.project("studentIds").
and("firstName").previousOperation());
AggregationResults<StudentResults> results = mongoTemplate.
aggregate(studentAggregation, StudentResults.class);
List<StudentResults> studentResultsList = results.getMappedResults();
return studentResultsList;
}
}
Using the above code, I am able to retrieve the List<String> studentIds successfully, but I need to retrieve List<Student> students using Aggregation.group()? Can you help?
Change your TypedAggregation part to below and add students field to StudentResults
TypedAggregation<Student> studentAggregation = Aggregation.newAggregation(Student.class,
Aggregation.group("firstName").
push("$$ROOT").as("students"));
$$ROOT will push the whole document.
Update:
TypedAggregation<Student> studentAggregation = Aggregation.newAggregation(Student.class,
Aggregation.group("firstName").
push(new BasicDBObject
("_id", "$_id").append
("firstName", "$firstName").append
("lastName", "$lastName")).as("students"));

Querying Embedded document in MongoDB using Mongo Template

I have the above domain structure where I have list of Companies in the product and the aim is not make entry in mongoDB when I have exact match for companies & productId already present in the DB.
#Entity
public class Mobile {
#Id
private Integer id;
private String imei;
private Product productInfo;
// ...
}
#Entity
public class Product {
#Id
private Integer id;
private String productId;
private List<Company<?>> companies;
// ...
}
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY, property = "type")
#JsonSubTypes({
#JsonSubTypes.Type(name= "samsung", value = Samsung.class),
#JsonSubTypes.Type(name= "htc",value = Htc.class)})
public class Company<T> implements Serializable {
private static final long serialVersionUID = -8869676577723436716L;
private T companyInfo;
private String type;
// ...
}
I am using mongo template and I have tried to use find as shown below but id didn't work
template.find(Query.query(Criteria.where("product.companies").is(companList),Mobile.class);