Spring Data MongoDB index declaration for field of field - mongodb

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

Related

spring data mongodb: compare LocalDateTime query

I have the below object
#Document(collection = "qr_code")
public class QrCode implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private String qrCodeId;
#Field
private String codePay;
private LocalDateTime expiredIn;
}
I have this query to check if a codePay exists or not
boolean existsByCodePay(String codePay);
I want another query to check if a QrCode is expired or not, based on attribute expiredIn, that's to say the QrCode expired when expiredIn < LocalDateTime.now()
#Query(???)
boolean isQrCodeExpired(String codePay);
The raw mongodb query can be something like this :
{
"expiredIn":{
$gt : new Date()
}
}

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

How to query for entities by their string collection values LIKE

I have the following entity:
#Entity
public class SystemLogEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private long creationTime;
private String thread;
private int severity;
#Lob
private String message;
#ElementCollection(fetch = FetchType.EAGER)
#Lob
private List<String> stacktrace;
...
}
My Respository implements JpaSpecificationExecutor, which allows me to use Specifications to filter my db requests:
#Repository
public interface SystemLogRepository extends JpaRepository<SystemLogEntity, Long>, JpaSpecificationExecutor<SystemLogEntity> {
public List<SystemLogEntity> findAll(Specification spec);
}
For the simple field of the SystemLogEntity this works fine, the Predicate are straight forward.
Also if I filter for an exact item in a collection, the Predicate are still straight forward (in).
But how can I filter my SystemLogEntity after a stack trace collection item which is LIKE a given value?
In other words, I would e.g. like to filter SystemLogEntity after the term NullpointerException. Is this even possible with Predicate?
I hope this will work:
Specification<SystemLogEntity> stacktraceLike(String stacktrace) {
return (root, query, cb) -> cb.like(root.join("stacktrace"), "%" + stacktrace + "%");
}
More examples...

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