Find query with field value containing a single quote not supported
Closed this issue · 6 comments
Hi all,
I have troubles using Jongo to run a find query with a value containing a single quote. I've tried escaping it in several ways:
With:
db.mycollection.find( {'someField': 'value with \' inside'} )
The result is:
java.lang.IllegalArgumentException: Cannot parse query: {'someField': 'value with ' inside'}
at org.jongo.query.BsonQueryFactory.createQuery(BsonQueryFactory.java:168)
at org.jongo.Find.<init>(Find.java:47)
at org.jongo.MongoCollection.find(MongoCollection.java:90)
at org.jongo.MongoCollection.find(MongoCollection.java:86)
(...)
Caused by: com.mongodb.util.JSONParseException:
{'someField': 'value with ' inside'}
^
at com.mongodb.util.JSONParser.read(JSON.java:303)
at com.mongodb.util.JSONParser.parseObject(JSON.java:274)
at com.mongodb.util.JSONParser.parse(JSON.java:229)
at com.mongodb.util.JSONParser.parse(JSON.java:157)
at com.mongodb.util.JSON.parse(JSON.java:99)
at org.jongo.query.BsonQueryFactory.createQuery(BsonQueryFactory.java:129)
... 14 more
With:
db.mycollection.find( {'someField': 'value with \\\' inside'} )
The result is:
java.lang.IllegalArgumentException: Cannot parse query: {'someField': 'value with \' inside'}
at org.jongo.query.BsonQueryFactory.createQuery(BsonQueryFactory.java:168)
at org.jongo.Find.<init>(Find.java:47)
at org.jongo.MongoCollection.find(MongoCollection.java:90)
at org.jongo.MongoCollection.find(MongoCollection.java:86)
(...)
Caused by: com.mongodb.util.JSONParseException:
{'someField': 'value with \' inside'}
^
at com.mongodb.util.JSONParser.read(JSON.java:303)
at com.mongodb.util.JSONParser.parseObject(JSON.java:274)
at com.mongodb.util.JSONParser.parse(JSON.java:229)
at com.mongodb.util.JSONParser.parse(JSON.java:157)
at com.mongodb.util.JSON.parse(JSON.java:99)
at org.jongo.query.BsonQueryFactory.createQuery(BsonQueryFactory.java:129)
... 14 more
Config:
- Java 8
- Jongo 1.4.0 and 1.5.0 SNAPSHOT, same behaviour
- mongo-java-driver 3.10.1
- jackson-core 2.9.8
This seems to be legal from MongoDB point of view, right?
Any ideas?
Thx in advance,
Franck.
Hi,
Just as a follow up, I've been investigating this issue. I came up with a workaround that works although it's pretty nasty honnestly.
So here is the thing: the MongoDB driver can deal with strings marked with double or single quotes.
It can deal with strings in double quotes with escaped double quotes inside: "ab \"cd\" ef"
But it does not support strings in single quotes with escaped quotes inside: 'O\'Connel'
.
So, the workaround is, in Jongo, to replace all single quotes with double quotes except those that are escaped. Have a look at https://github.com/frmichel/jongo/blob/master/src/main/java/org/jongo/query/BsonQueryFactory.java lines 84-86.
Example: 'O\'Connel'
is transformed into "O'Connel"
.
So in my use case, with simple find queries, that works fine. Here is an example (in Scala):
// Note the \\ to escape the backslash, so that the string passed contains both characters:
// a backslash followed by a single quote
val q = "{'Lastname': 'O\\'Connel'}"
var results = jongoContext.getCollection("mycollecion").find(q)
Problem: what are the possible side effects of such a change?? Honestly I don't know...
If you want I can submit a pull request for that.
Regards,
Franck.
Hi @bguerout, thx for your answer.
As a matter of fact, I must admit that I had not tried that. Since Jongo's guidelines say that strings should use single quotes, I just blindly complied to that. But indeed, using double quotes works fine like in {"someField": "value with ' inside"}
.
Still, using strings with single quotes and escaping a single quote inside one string, like I was doing in {'someField': 'value with \' inside'}
, still does not work, and that fails in MongoDB's driver.
Anyway, there is a workaround, and I'm happy with that. ;)
Franck.
As a workaround you can use a parameter # :
@Test
public void canBindAParameterWithSingleQuoteInParameter() throws Exception {
collection.insert("{someField:#}", "value with ' inside");
long nb = collection.count("{someField:#}", "value with ' inside");
assertThat(nb).isEqualTo(1);
}
Note that this is the same as using double quotes
H @bguerout, thx for the tip, however in my case the query comes from a configuration file, so that I can't use the '#' writing.
Franck.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.