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?

4 Answers 4

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));
Sign up to request clarification or add additional context in comments.

Comments

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

3 Comments

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
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?
I'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>}})
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 {...}

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.