Spring Data - MongoDB indexing DBRef

10,210

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();
Share:
10,210
Modi
Author by

Modi

Updated on June 08, 2022

Comments

  • Modi
    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
    Modi about 11 years
    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
  • Ori Dar
    Ori Dar about 11 years
    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?
  • Modi
    Modi about 11 years
    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>}})