I am trying to query based on UUID with Spring Data - Mongo template. The generated query does not return the expected document. When I try to run the query in shell using new BinData(type, base64) it returns the documents. The generated query a uses {"$binary" : "base64", "$type" : "03} as the matching filter.
I have an Object that has id configured as UUID type. Here is the object type.
@Data
@NoArgsConstructor
@Document(collection = "person")
public class Person {
@Id
private UUID id;
private String firstName;
private String lastName;
...
}
Here is the custom repository implementation method.
...
Query findPersonQuery = new Query();
findPersonQuery.addCriteria(Criteria.where("_id").is(personId));
final Person person = mongoTemplate.find(findPersonQuery, Person.class);
// process and return person after
....
The above code seems to generate a parsed query as such when I pass in the UUID. UUID is a02b2900-b871-11e9-a2a3-2a2ae2dbcce4
{ "_id" : { "$eq" : { "$binary" : "6RFxuAApK6DkzNviKiqjog==", "$type" : "03" } } }
When I run this in mongo shell it returns nothing. In the repository it returns nothing.
However, when I put the following query in mongo shell I get the correct person object
db.getCollection('person').find({ "_id" : new BinData(3, "6RFxuAApK6DkzNviKiqjog==")})
I expected generated query to return the person with a UUID of a02b2900-b871-11e9-a2a3-2a2ae2dbcce4
Questions:
- What is the difference between $binary operator and BinData when passed into shell.
- How can I get spring data and mongoTemplate to generate the correct query. 2.1 Is it possible without writing a custom query?
I know we can do something like BasicQuery as shown below but is there a way to avoid it since we have to now provide a custom encoder of base 64 rather allow JPA style to convert UUIDs to persistence layer
final ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
buffer.putLong(personId.getMostSignificantBits());
buffer.putLong(personId.getLeastSignificantBits());
final String base64PersonId = Base64.encodeBase64String(buffer.array());
final String query = String.format("{ _id: new BinData(3,\"%s\")}", JSONObject.escape(username), base64PersonId);
return new BasicQuery(query);