Querying Embedded document in MongoDB using Mongo Template - mongodb

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

Related

Spring Data MongoDB not able to load reference collection (#DocumentReference)

In Spring data findAll method reference object is coming as null
I am using Reactive Mongo Repository
Ex Parent Object
#Data
#Document(collection = "country")
public class CountryBean {
#Id
private String id;
private String name;
}
Child Object
#Document(collection = "city")
public class CityBean {
#Id
private String id;
#Field(name = "name")
private String name;
#Field(name = "city_code")
private String cityCode;
#Field(name = "show_city")
private boolean showCity;
#DocumentReference(lazy = false)
private StateBean state;
}
Country Collection
State Collection (Here we can see the country Attribute)
But When trying to fetch from DB, I am getting country attribute as null. Tried both lazy true/false, but not getting country object along with state object.
#GetMapping("/get-all-state")
Flux<StateBean> allState() {
Flux<CountryBean> ct = countryRepository.findAll();
Flux<StateBean> bean= stateRepository.findByCountry(ct.blockFirst());
return bean;
}
[{"id":"6237a912850ceb6261998a53","name":"Bangalore","statecode":"39","country":null},{"id":"6237a94a850ceb6261998a55","name":"delhi","statecode":"39","country":null}]

JPA how to set foreign id - in Embeddable id - that is generated

My use case is: I have a Product with multi language name. To have at most one name per language a translation should be identified by locale + productId.
My problem is to get it working with a generated productId. This are the entities:
e.g. in oracle i get: "ORA-01400: cannot insert null into ."PRODUCT_NAME"."FOREIGN_ID""
Product:
#Entity
#Data
public class Product {
#Id
#GeneratedValue
private Long id;
#Column(unique = true)
private String articleNumber;
/**
* Localized name of the product.
*/
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
#MapKey(name = "nameId.locale")
private Map<Locale, ProductName> names = new HashMap<>();
}
ProductName:
#Entity
#Data
public class ProductName {
#EmbeddedId
private TranslationId nameId;
private String name;
}
TranslationId:
#Embeddable
#Data
public class TranslationId implements Serializable {
private static final long serialVersionUID = 3709634245257481449L;
#Convert(converter = LocaleConverter.class)
private Locale locale;
private Long foreignId; //<-- this is null, should reference product
}
Is there a way to get this working without having to save the product first without the name? Without a generated id it is working of course - i just set same id for both.
I would like to re-use the translation id for other translated fields of other entities.

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

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