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

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

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!

Spring boot mongo db index (unique=true) not working

I have the below class as my document.
#Data
#Builder
#Document(collection = "test")
public class TestData {
#Id
private String id;
private String name;
#Indexed(unique = true)
private String hash;
}
Even if I'm using Indexed with unique enabled, I'm able to insert duplicate documents into collection.
But if I generate index in mongo shell then it is working.
Is there any way where I can specify unique Index through code only?
This is how the compound index is used in my code
#Getter
#Setter
#Document
#CompoundIndexes({
#CompoundIndex(name = "name_author_idx", def = "{'name' : 1, 'author' : 1}", unique = true, background = true)})
public class Book implements Transformer {
#Id
private String id;
#Field(name = "name")
private String name;
#Field(name = "author")
private String author;
#Field(name = "qty")
private Integer qty;
#Field(name = "price")
private Double price;
#Field(name = "created_time")
private LocalDateTime createdTime = LocalDateTime.now();
}
Please use following code on application.properties file on spring boot application it will work.
spring.data.mongodb.auto-index-creation: true
Thank you
If you're having a configuration component you should override the autoIndexCreation method like this:
#Configuration
public class MongoConfiguration extends AbstractMongoClientConfiguration
{
#Override
protected boolean autoIndexCreation() {
return true;
}}

Spring Data MongoDB index declaration for field of field

I have the following Spring Data MongoDB document:
#Document(collection = "messages")
#CompoundIndexes({ #CompoundIndex(name = "chatId_messageId", def = "{'chatId': 1, 'messageId': 1}") })
public class Message implements Serializable {
private static final long serialVersionUID = -1590112217771926691L;
#Id
private String id;
private Long chatId;
private Integer messageId;
private Post post;
}
the Post model(which is not Spring Data MongoDB document) looks like:
public class Post implements Serializable {
private static final long serialVersionUID = -886664249197573502L;
private String id;
}
I'd like to add index to the Message.post.id field.
How it can be done with Spring Data MongoDB and Message.post field declaration in Message document ?
If you want to add Message.post.id to an already compound index, then do it like
#Document(collection = "messages")
#CompoundIndexes({ #CompoundIndex(name = "chatId_messageId", def = "{'chatId': 1, 'messageId': 1, 'Message.post.id' : 1}") })
public class Message implements Serializable {
private static final long serialVersionUID = -1590112217771926691L;
#Id
private String id;
private Long chatId;
private Integer messageId;
private Post post;
}
Compound indexes are indexes that have more than one indexed field, so ideally, the most restrictive field should be to the left of the B-tree. If you want to index by sex and birth, for instance, the index should begin by birth, as it is much more restrictive than sex.
Or if you want to treat it as a saperate index, then create index using #Indexed like
public class Post implements Serializable {
private static final long serialVersionUID = -886664249197573502L;
#Indexed
private String id;
}
Updated
For more info regarding how queries with sub fields of compound index works, check Documentation

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

Datanucleus mongodb references

Can I fetch fields by DBRef?
I have to separate collection mapped to:
#PersistenceCapable(table = "group")
public class MyGroup
{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY, column = "_id")
private String id;
private String name;
private Person person;
// getters/setters
...
}
#PersistenceCapable(table = "people")
public class Person
{
#PrimaryKey
#Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY, column = "_id")
private String id;
private String firstName;
private String lastName;
// getters/setters
...
}
I'd like to get person name (currently I got person as null):
MyGroup myGroup = persistenceManager.getObjectById(MyGroup.class, "5230a918ac8c95fd3d9a3dfa")
myGroup.getPerson().getFirstName();
and perform queries:
Query query = persistenceManager.newQuery(MyGroup.class);
query.setFilter("persone.firstName == \"Tester\"");
DataNucleus doesn't support DBRef on MongoDB datastore:
http://www.datanucleus.org/servlet/forum/viewthread_thread,7924#38188