Spring boot / mongo wont create index with the index annotation - mongodb

I have the following:
#Document(collection = "linkmetadata")
public class LinkMetaData {
#Indexed(unique = true)
private String url;
...
}
But whenever it creates the collection it doesn't create any index for the url field, it's like it just ignores the annotation. Any idea why this is?
Edit: no index is created upon insertion of data either. And when I try to fetch data for a specific url it throws an error that the url key is not unique if I entered the same url twice, but it doesn't care about inserting the unique key since there is no index..

use auto-index-creation: true in your application properties.Add billow line in your application.properties
spring.data.mongodb.auto-index-creation: true

I found the problem. I had another collection also with a url field marked as unqiue. I had to specify the name of the index on one of them otherwise it seems that it considered that the index already exists even though it was on two different collections
#Indexed(name = "meta_url_index_unique", unique = true)
private String url;

Edit: This answer was before the author updates his question
I believe you need to use the #Document annotation on top the class declaration
So your class should be
#Document
public class LinkMetaData {
#Indexed(unique = true)
private String url;
...
}

I Also had the same issue. The one that solved my issue was adding the index from the mongo db level
db.city.createIndex( { "name": 1 }, { unique: true } );

Related

mongodb - compound unique index using spring data not working

I am trying to create unique compound index in mongodb using spring data.
But I see that the index is not created and the duplicate document is created in the DB.
My entity class:
#Document
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
#CompoundIndexes(
#CompoundIndex(name = "daybook_index", def = "{'date' : 1, 'vehicleNumber' : 1}", unique = true)
)
public class Daybook {
private String date;
private String vehicleNumber;
private String unit;
}
I am using repository.insert() method to create the document.
When I see in mongo express I see only one index created on _id and the index defined in the entity class is not created.
Is it a bug in spring data or am I doing something wrong?
P.S.: I tried to delete the collection too before running the application but didn't help.
As of Spring Data MongoDB 3.0, automatic index creation is turned off by default.
To turn it on you might use the proper flag overriding the method from MongoConfigurationSupport:
public class MongoConfiguration extends AbstractMongoClientConfiguration {
.....
#Override
protected boolean autoIndexCreation() {
return true;
}
}
otherwise you might create the index with appropriate instructions.
mongoOperations.indexOps(Daybook.class).ensureIndex(new Index().on("date", Direction.ASC).on("vehicleNumber", Direction.ASC).unique());
As #Saxon mentioned:
Spring Data MongoDB 3.0, automatic index creation is turned off by default.
Instead of adding code, I am able to create the index by adding the spring data configuration in application.properties
spring.data.mongodb.auto-index-creation=true

Spring MongoRepository not returning id field of nested objects [duplicate]

I have a document with an array field with
"chapters": [
{ "id" : "14031871223912313", ...}
...
]
I would like to query return the id's with Spring Data's MongoTemplate using the following:
class Chapter {
private String id;
public String getId() {
return id;
}
}
This way the id is not populated. I have tried using the different mapping options with #Field described here http://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mapping.conventions.id-field
What am I doing wrong? I know I can always to back to mongo java driver, but I thought this should work.
Thanks in advance for any help.
Found a solution. It is populated via:
#Field("id")
private String chaperId
In MongoDB id's are _id, and every document in mongo has an _id. From the document you linked to, Spring will map #Field String id to mongo's _id field. You probably want to use a #Field('id') String id field mapping to indicate that the field you want is id not _id.

spring data query filter on property not on field

I have a pojo that contains this field:
#Transient
private EventType eventType;
where EventType in an enum:
To persist this field I use the property access:
#Access(AccessType.PROPERTY)
#Column(name = "EVENT_CODE")
String getEventTypeCode() {
return eventType.getEventCode();
}
void setEventTypeCode(String eventCode) {
eventType = EventType.decode(eventCode);
}
I need to filter on that property but with spring data I don't know how to do it.
Is it possible?
Massimo
You can look into Spring Data Specifications. You use them by calling repository.findAll(s);
Specifications allow you add on arbitrary conditions to your query, including the filter you want to add. See here:
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#specifications

How can I query to find mongo entities whose list of sub-entities contain a field matching a string?

I have a collection of entities that look like this:
public class ClientEntity {
#Id
private String id;
#Indexed(unique = true)
private String clientId;
private String name;
#DBRef
private List<ClientMachineEntity> machines;
...
}
...where ClientMachineEntity looks like:
public class ClientMachineEntity {
#Id
private String id;
#Indexed(unique = true)
private String clientMachineId;
private String hostName;
...
}
I have a working search that finds ClientEntities by matching against "clientId" and "name":
public List<ClientEntity> searchByIdAndName(String id, String name) {
Criteria idCriteria = Criteria.where("clientId").regex(id, "i");
Criteria nameCriteria = Criteria.where("name").regex(name, "i");
Query query = new Query(new Criteria().orOperator(idCriteria, nameCriteria));
...
}
So my question is, how can I expand this search so that it also matches against "clientMachineId" in the list of sub-entities? I tried adding the following criteria:
Criteria machineCriteria = Criteria.where("machines.clientMachineId").regex(id, "i");
...but that doesn't work, presumably because machines is a LIST of entities, not just a single sub-entity.
UPDATE: It seems like what I'm looking for is the .elemMatch() functionality, but when I try that:
Criteria machineCriteria = Criteria.where("machines").elemMatch(Criteria.where("clientMachineId").regex(id, "i"));
...I get the following error:
org.springframework.data.mapping.model.MappingException: No mapping metadata found for class com.mongodb.BasicDBObject
You can't query by fields in subentities linked with DBRef. If ClientMachineEntity would be embedded in ClientMachine - then you could use dot notation or $elemMatch depending on needs.
In your particular example - couldn't field ClientMachineEntity.clientMachineId be saved as _id and used as a primary key? Then you could get the results you need - take a look at: How to query mongodb with DBRef
My suggestion for development with Spring Data MongoDB is - first learn how to (and if it's possible) do it in plain Javascript with MongoDB console, then learn how to do the same with Spring Data MongoDB.

How to map Grails domain object to a specific mongodb table name

I've setup a simple grails app looking at a mongodb.
My domain object looks like this:
class GoogleSearch {
String _id;
String id;
String query;
String site;
Object results;
Date date;
static mapping = {
table 'google_searches'
}
static constraints = {
}
}
However when I run the grails app up, it keeps reading/writing to a table named "googleSearch"
Does anyone know how I can override this default naming? Is it a gorm/mongodb thing?
Cheers
Basics of MongoDB. There is no concept of table. It is always collections. :)
Refer mapping as collection 'google_searches'.
For more details you can refer Grails MongoDB plugin.