Reputation: 39
I have a data class with a String Id and I'm saving it into the mongoDB with a null value to get an autogenerated replacement.
@Document(collection="applications")
@TypeAlias(Constants.Application)
public class DataApplication implements IApplication{
@Id
@Field("id")
private String id = null;
...
}
This works as expected however I'm facing a problem in that I cannot seem to findById from the Spring Mongo Repo. It is capable of persisting and retrieving without problems, creating BSON like
{
"_id" : ObjectId("5ef9a579bafa09b36225e743c"),
Other fields and things
}
However, this seems to be specifically about when attempting to find using the id field. Its very weird that it isn't using the Id field name I specified, however as when I retrieve multiple objects at once they convert back into POJOs as expected I do not believe this is an issue.
From what I can see this seems to be a result of the MongoDB storing the values as ObjectId's, as I am able to retrieve by Id when I persist an object with a String Id value, when I pull the Applications into Java to compare, or when I create Examples that match all fields except Id, however Examples fails when I set an Id to compare against.
Prevent Spring Data for Mongo to convert ids to ObjectId seems to be related as it mentions the underlying query structure, unfortunately I seem to have the opposite problem.
Upvotes: 1
Views: 6780
Reputation: 11
For details on how MongoDB handles _id fields and to address the issue of using ObjectId for new documents and String for updates, please refer to this: enter link description here
Upvotes: 0
Reputation: 14287
@Field
annotation is used to define custom metadata for document fields. For example:
@Field(targetType = DECIMAL128)
private BigDecimal value;
@Field("fName")
private String firstName;
When you defined @Field("id") private String id = null;
it is interpreted as the field id
as another field id
not the document identifier field _id
. Because, the annotation's name
attribute is specified as "id". You can verify this as well in the following example using the Person
Pojo class:
public class Person {
@Field("id")
private String id = null;
private String name;
public Person(String name) {
this.name = name;
}
public void setId(String id) {
this.id = id;
}
// other get / set methods ...
public String toString() {
return "id: " + id + ", " + name;
}
}
Using MongoRepository
methods insert and query documents in person
collection:
Person p1 = new Person("J.Doe");
//p1.setId("000");
repo.insert(p1);
List<Person> list = repo.findAll();
list.forEach(System.out::println);
This will insert a document (as queried from the mongo
shell) and print the toString
representation as:
{ "_id" : ObjectId("5ef5c92b70babc5a961350e5"), "name" : "J.Doe", "_class" : "com.example.demo.Person" }
Prints as: id: null, J.Doe
If you un-comment the code p1.setId("000");
and run it again, you will find the following:
{ "_id" : ObjectId("5ef5cab8306d071b13d3c16e"), "id" : "000", "name" : "J.Doe", "_class" : "com.example.demo.Person" }
And, prints as: id: 000, J.Doe
The code is behaving alright. Note the two fields, the _id
and id
. The @Field
is to be used for customizing a document field.
To properly indicate the id
field is to be used for _id
document key field you can use the following. When the document is created the _id
value will be the driver generated ObjectId
:
id
field as @Id
, @MongoId
or the @Field
(without the
name
attribute).Note on Annotations:
Upvotes: 2