[JAVA-2224] JsonReader does not support BsonRegularExpression Created: 14/Jun/16  Updated: 28/Jun/17  Resolved: 28/Jun/17

Status: Closed
Project: Java Driver
Component/s: JSON
Affects Version/s: 3.0.0
Fix Version/s: 3.5.0

Type: Bug Priority: Major - P3
Reporter: Guillaume Smet Assignee: Unassigned
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates JAVA-2447 Implement Extended JSON specification Closed

 Description   

When trying to parse the following query:

{ $query : { author : { $regex : /^Oscar/ } }, $orderby : { name : 1 } }

we end up with the following error:

org.bson.json.JsonParseException: JSON reader expected a string but found 'BsonRegularExpression{pattern='^Oscar', options=''}'.
	at org.bson.json.JsonReader.visitRegularExpressionExtendedJson(JsonReader.java:940)
	at org.bson.json.JsonReader.visitExtendedJSON(JsonReader.java:587)
	at org.bson.json.JsonReader.readBsonType(JsonReader.java:139)

This is due to the fact that JsonReader#visitRegularExpressionExtendedJson is not prepared to get directly an already parsed BsonRegularExpression.

This is kinda annoying because we can't support this type of native query in Hibernate OGM.

PR to come.



 Comments   
Comment by Jeffrey Yemin [ 16/Mar/17 ]

This will be fixed in scope of JAVA-2447, so resolving as a duplicate.

Comment by Guillaume Smet [ 15/Jun/16 ]

Hi Jeff,

Sorry for the delay, been busy on other things.

Note that the issue you mention in your last example already exists with the string syntax, it's not directly related to this patch.

The fact is that I'm not even sure you're right on the way we should interpret it as, in strict mode, a BsonRegularExpression will be written like that at the end:

case STRICT:
                    writeStartDocument();
                    writeString("$regex", regularExpression.getPattern());
                    writeString("$options", regularExpression.getOptions());
                    writeEndDocument();
                    break;

so if you rewrite the document to JSON in strict mode, you will end up with:

{ "company":
     {
          $regex: { $regex: "acme.*corp" },
          $options: "i",
          $eq: "acmeblahcorp" 
     }
}

which is not supported by the server.

I've spent some time on this issue but I didn't find any solution. I don't think there's a way to support this syntax.

I did improve my patch though to deal with the

{ $regex: /test/, $options: 'ixms' }

case correctly. Force pushed the PR.

Thoughts?

Comment by Jeffrey Yemin [ 14/Jun/16 ]

I see now. I had forgotten that $regex is serving double-duty: it's both the key that identifies a regular expression in MongoDB extended JSON, and it's a query operator. The problem is that JsonReader doesn't know anything about the query operators, so is trying to parse this string as extended JSON and so expects a string and not a pattern as the value of $regex.

We have to be careful how we fix this. Take this case derived from the docs:

{ company: { $regex: /acme.*corp/, $options: 'i', $eq: 'acmeblahcorp' } }

This should parse into something like:

- StartDocument
  - Field
    - Name: "company"
    - Value
       - StartDocument
       - Field
          - Name: "$regex"
          - Value: BsonRegularExpression("acme.*corp")
       - Field
          - Name: "$options"
          - Value: BsonString("i")
       - Field
          - Name: "$eq"
          - Value: BsonString("acmeblahcorp")
       - EndDocument
- EndDocument

If we just try to parse it the normal way but allow the value of $regex to use the shell's pattern syntax, we'll run into a problem once we hit the $eq.

Comment by Guillaume Smet [ 14/Jun/16 ]

Hi Jeff,

Thanks for your feedback.

AFAICS, that's not what is documented in https://docs.mongodb.com/manual/reference/operator/query/regex/:

To use $regex, use one of the following syntax:

{ <field>: { $regex: /pattern/, $options: '<options>' } }
{ <field>: { $regex: 'pattern', $options: '<options>' } }
{ <field>: { $regex: /pattern/<options> } }

It seems that the syntax from the issue should be supported or the documentation updated.

Comment by Jeffrey Yemin [ 14/Jun/16 ]

Hi Guillaume,

This is by design. JsonReader will parse either MongoDB extended JSON, which would look like this:

{ author : { $regex : "^Oscar" } }

or MongoDB shell-style "JSON", which would look like this

{ author : /^Oscar/ }

What you are attempting is a mix of the two, which is not supported anywhere as far as I know.

From where are you getting the strings like the one in the description?

Comment by Guillaume Smet [ 14/Jun/16 ]

Pull request: https://github.com/mongodb/mongo-java-driver/pull/355

Generated at Thu Feb 08 08:56:39 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.