11

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?

Community
  • 1
  • 1
Modi
  • 2,200
  • 4
  • 23
  • 37

4 Answers4

9

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));
AntonioOtero
  • 1,759
  • 1
  • 14
  • 16
5

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

Ori Dar
  • 18,687
  • 5
  • 58
  • 72
  • 1
    Thank'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 – Modi Apr 05 '13 at 10:23
  • As 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? – Ori Dar Apr 05 '13 at 10:46
  • I'm using Mongo DB and shell version 2.4.1 . I'm able to execute the next queries: db.b.find({"a.$id" : },{"a.$id" : 1}) and db.b.find({"a.$id" : },{"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" : }}) – Modi Apr 06 '13 at 17:56
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 {...}
madx
  • 6,723
  • 4
  • 55
  • 59
1
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();
saurabh
  • 2,463
  • 1
  • 18
  • 8