2

Following structure:

@Document 
public class Palace {
    @Id
    private String id;
    private Location location;
    // additional attributes, getter, setter 
}

.

public class Location {
    private String id;
    // additional attributes, getter, setter
}

As far as I understand the concept of ObjectId, there can be only one ObjectId (_id) in a MongoDB document and it must be at the root level of the document. But when inserting data via Spring Boot 1.5.14 I get the followng structure:

{
    "_id" : ObjectId("5b05387a8db58e0001d38851"),
    "location" : {
        "_id" : ObjectId("5ae712d1b2b197000132cd9b"),
    }
}

My question is: Is this the expected behaviour in spring-data-mongo? I would have expected the following structure:

{
    "_id" : ObjectId("5b05387a8db58e0001d38851"),
    "location" : {
        "id" : "5ae712d1b2b197000132cd9b",
    }
}

If I annotate the Location id with @Field

public class Location {
    @Field("id")
    private String id;
    // additional attributes, getter, setter
}

then the Document is saved as expected, but querying with repository method

getPalaceByLocationId()

won't give any results.

8
  • Try getPalaceByLocation_Id() with @Field. See if it works? Commented Jun 25, 2018 at 9:57
  • getPalaceByLocation_Id() has the same result. Maybe this is a bug in spring-data-mongo, or the magic how to identify a MongoDb ObjectId is searching for ID fields in nested classes which is imho wrong. Commented Jun 25, 2018 at 14:19
  • getPalaceByLocation_Id() works for me when you have @Field("id"). Cross check. Commented Jun 25, 2018 at 18:36
  • How are you setting id field of location? are you setting it urself? Commented Jun 26, 2018 at 8:37
  • Yes, calling setId() Commented Jun 26, 2018 at 8:57

1 Answer 1

1

Some insights into id field. id field is treated a bit differently in spring-data-mongodb.

Check out the documentation.

Extending the documentation for your case, when you declare an id like this

public class Location {
    private String id;
    // additional attributes, getter, setter
}

It is stored as _id in database. You can cross check by looking into the database. The same is true when you annotate it with @Id

{
    "_id" : ObjectId("5b31fad36a19cc45db205056"),
    "location" : {
        "_id" :  ObjectId("5ae712d1b2b197000132cd9b")
    }
}

5ae712d1b2b197000132cd9b is the id you had set using location.setId(). Internally it is converted to ObjectId and stored as _id.

But when you add @Field annotation, things change. Let's assume you add an annotation like this

@Field("id")
private String id;

Then the document looks like this in database.

{
    "_id" : ObjectId("5b31fad36a19cc45db205056"),
    "location" : {
        "id" :  "5ae712d1b2b197000132cd9b"
    }
}

With this the problem is you cannot retrieve by id. Because when you write findPalaceByLocationId or findByLocation_Id it(spring-data) tries to look for _id field which doesn't exist.

Only way around this is just use it like this

@Field
private String id;

or just

private String id;

This will create _id in database and you can do findByLocationId

I know it is a bit sketchy. But that is how it works.

And regarding

As far as I understand the concept of ObjectId, there can be only one ObjectId (_id) in a MongoDB document and it must be at the root level of the document.

that is incorrect.

A small info table regarding mapping

Field definition         Resulting Id-Fieldname in MongoDB  

String id                      _id  
@Field String id               _id  
@Field('x') String id           x    
@Field('id') String id          id (InAccessible)   
@Id String x                   _id  
@Field('x') @Id String x       _id 
Sign up to request clarification or add additional context in comments.

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.