Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cannot find by UUID field in PanacheMongoEntity #10941

Closed
rmanibus opened this issue Jul 23, 2020 · 10 comments · Fixed by #10965
Closed

cannot find by UUID field in PanacheMongoEntity #10941

rmanibus opened this issue Jul 23, 2020 · 10 comments · Fixed by #10965
Labels
Milestone

Comments

@rmanibus
Copy link
Contributor

rmanibus commented Jul 23, 2020

When using the following PanacheMongoEntity:

@MongoEntity()
@Data
public class Event extends PanacheMongoEntity {

    public UUID userId;
    public UUID objectId;
    public LocalDateTime createdAt;
}

The following request always return 0, even if some data is present:

Event.count("objectId = ?1", someObject.getUuid())

My connection String is :

quarkus.mongodb.connection-string = mongodb://localhost:27017/?uuidRepresentation=STANDARD

In an other entity, I use UUID as primary ID and I can find them with findById(UUID).

Replacing UUID by String make this working.

I'm using Quarkus 1.6.1

@rmanibus rmanibus added the kind/bug Something isn't working label Jul 23, 2020
@quarkusbot
Copy link

/cc @FroMage, @loicmathieu
/cc @loicmathieu

@loicmathieu
Copy link
Contributor

loicmathieu commented Jul 24, 2020

@rmanibus How are your UUID fields rendered inside the MongoDB collection? Are they String ? Did you persist your entity via the same code ?

Can you please try with the following code:

Event.count("objectId = ?1", someObject.getUuid().toString())

MongoDB with Panache uses the MongoDB typed mongo collection, and MongoDB provides a UuidCodec so we may do something special to support UUID as a query parameter.

@rmanibus
Copy link
Contributor Author

rmanibus commented Jul 24, 2020

They are not stored as String, when I changed objectId type from UUID to String I got a incompatible type error because of the data that was previously stored, looking at the error message, It seems they where stored as binary.

Yes I persisted the data with panache ( .persist() )

What do you mean by try the following code ? it's exactly what I tried already :)

@rmanibus
Copy link
Contributor Author

you mean doing a toString() on the UUID ?

@loicmathieu
Copy link
Contributor

you mean doing a toString() on the UUID ?

Yes I hit send too quickly ;)

It seems they where stored as binary

Yes, I what the UuidCodec does and it do store them as binay. We will need to implements special treatment for UUID inside MongoDB with Panache to make this works.

@rmanibus
Copy link
Contributor Author

toString() is not working either (it is consistant with the fact that UUID are stored as binary)

@rmanibus
Copy link
Contributor Author

rmanibus commented Jul 25, 2020

Looking at my data in mongo client I have:
{ "_id" : ObjectId("5f1a93cce9e05f30736a88fd"), "createdAt" : ISODate("2020-07-24T09:54:52.156Z"), "userId" : UUID("7f000101-7339-15ad-8173-3946066b0001"), "videoId" : UUID("7f000101-7370-1f68-8173-70afa71b0000") }

@rmanibus
Copy link
Contributor Author

rmanibus commented Jul 25, 2020

Well, it's better, with the PR the request sent to the db is:

Sending command '{"aggregate": "Event", "pipeline": [{"$match": {"videoId": {"$binary": {"base64": "fwABAXNwFh6Bc3CowKkABA==", "subType": "03"}}}}, {"$group": {"_id": 1, "n": {"$sum": 1}}}], "cursor": {}, "$db": "videoplatform"}' with request id 16 to database videoplatform on connection [connectionId{localValue:3, serverValue:36}] to server localhost:27017

so the UUID is correctly transformed to binary but I still get a 0 count

Which is weird because the following query return values with mongo client:

db.getCollection("Event").find({ videoId: UUID('7f000101-7370-1f68-8173-70afa71b0000')})

@rmanibus
Copy link
Contributor Author

rmanibus commented Jul 25, 2020

That's because it is parsed as a legacy UUID.


    /**
     * A UUID in a driver dependent legacy byte order.
     */
    UUID_LEGACY((byte) 0x03),

    /**
     * A UUID in standard network byte order.
     */
    UUID_STANDARD((byte) 0x04),

Values fetched by findById() have the correct sub type

{"find": "VideoViews", "filter": {"_id": {"$binary": {"base64": "fwABAXNwFh6Bc3CpJWgABQ==", "subType": "04"}}}, "limit": 1, "singleBatch": true, "$db": "videoplatform"}' with request id 22 to database videoplatform on connection [connectionId{localValue:4, serverValue:47}

@rmanibus
Copy link
Contributor Author

rmanibus commented Jul 25, 2020

There is this weird function in org.bson.json.JsonReader:

    private BsonBinary visitUUIDConstructor(final String uuidConstructorName) {
        verifyToken(JsonTokenType.LEFT_PAREN);
        String hexString = readStringFromExtendedJson().replaceAll("\\{", "").replaceAll("}", "").replaceAll("-", "");
        verifyToken(JsonTokenType.RIGHT_PAREN);
        byte[] bytes = decodeHex(hexString);
        BsonBinarySubType subType = BsonBinarySubType.UUID_STANDARD;
        if (!"UUID".equals(uuidConstructorName) || !"GUID".equals(uuidConstructorName)) {
            subType = BsonBinarySubType.UUID_LEGACY;
        }
        return new BsonBinary(subType, bytes);
    }

which is passed the value "UUID" but the condition make it always return UUID_LEGACY

Edit: it seems fixed on the In the 4.1.x branch of the driver (they removed the legacy).

I created a PR to fix this in the 4.0.x branch:

mongodb/mongo-java-driver#556

Should I upgrade the mongo client to 4.1.0-rc0 in this PR ? (I tried and it's working as expected, subtype is 04)

@gsmet gsmet modified the milestones: 1.8.0 - master, 1.7.0.CR2 Aug 4, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants