Spring Data - MongoDB indexing DBRef
Solution 1
You can create the index with the mongo shell, but if you want to do it through code and since you are using spring-data-mongodb, use this:
mongoTemplate.indexOps(B.class).ensureIndex(new Index().on("a", Order.ASCENDING));
You can also specify the name of the collection if the name of your class doesn't match it:
mongoTemplate.indexOps("b").ensureIndex(new Index().on("a", Order.ASCENDING));
Solution 2
I think this will work:
@CompoundIndex(name = "b_ref_to_a", def = "{'a.id' : 1}")
@Document(collection = "b")
public class B {...}
If not, you can call mongoTemplate.indexOps("b").ensureIndex(...)
in a method annotated with @PostConstruct
or so
Solution 3
I had the same problem, for me the orid's solution worked but I had to wrap the @CompoundIndex inside a @CompoundIndexes otherwise it didn't work (I'm using Spring Roo).
@CompoundIndexes({
@CompoundIndex(name = "b_ref_to_a", def = "{'a.id' : 1}")
})
@Document(collection = "b")
public class B {...}
Solution 4
DBObject indexOptions = new BasicDBObject();
indexOptions.put("a", 1);
indexOptions.put("b", 1);
indexOptions.put("c.d", 1);
indexOptions.put("e.f", 1);
CompoundIndexDefinition indexDefinition =
new CompoundIndexDefinition(indexOptions);
mongoTemplate.indexOps(.class).ensureIndex(indexDefinition);
for unique index you can add mongoTemplate.indexOps(.class).ensureIndex(indexDefinition).unique();
Modi
Updated on June 08, 2022Comments
-
Modi almost 2 years
I'm using spring-data-mongodb-1.2.0.RELEASE. I have two classes A and B where B has a reference to A and it is annotated with @DBRef.
Class A:
@Document(collection = "a") public class A { @Id public String id; /** The TicketGrantingTicket this is associated with. */ @Field public String name; public A(String id, String name) { this.id = id; this.name = name; } }
Class B:
@Document(collection = "b") public class B { @Id public String id; @Field public String name; @DBRef @Indexed public A a; public B(String id, String name, A a) { super(); this.id = id; this.name = name; this.a = a; } }
Since I'm quering for all instances of B that are refering to a certain A:
B fromDB = mongoOperations.findOne(Query.query(Criteria.where("a.$id").is(a1.id)), B.class);
I need it to be indexed.
After the first insertion of a B instance into MongoDB an index should be created. As can be seen below it doesn't:
Does anyone know how can I create such an index ?
In addition it looks like the DBRef filed (as can be seen by the mongo shell) does not match to the format as it is defined at MongoDB documentation.
Am I missing something here?
-
Modi about 11 yearsThank's for the help. Still, why the index is not created altough it is annotated with @Indexed? and another open question is why does MongoDB documentation shows the DBRef in a different format than the one that can be seen at the Mongo shell snapshot
-
Ori Dar about 11 yearsAs for the @Indexed, it's not really documented, but I don't think it's suitable for complex types, anyway never worked for me. Personally, I use one of the two methods mentioned above to index "complex" type. As for second issue, what version of mongodb shell are you using? try
db.d.find({},{"a.$ref" : 1, "a.$id" : 1})
what do you get? -
Modi about 11 yearsI'm using Mongo DB and shell version 2.4.1 . I'm able to execute the next queries: db.b.find({"a.$id" : <val>},{"a.$id" : 1}) and db.b.find({"a.$id" : <val>},{"a.$ref" : 1}) but I can't include a.$ref and a.$id on the projection argument and the condition argument must include "a.$id" . Most important is that in order to use the index that was created on 'a', the query element must include the a.$id and a.$ref: db.b.find({a:{"$ref" : a, "$id" : <val>}})