Casbah: How to Update and Embedded Object When Field Names Have Spaces? - mongodb

Supposing I had the following document in a database:
{"_id":"test", "with space":{"a name":1}}
How can I write a $set query in Casbah to update "with space"."a name" to 2?
I was thinking something along the lines of:
collection.update(MongoDBObject("_id" -> "test"), "'with space'.'a name'" $set 2)
But what if my field names were unknown and I had to compose them at runtime? Is there any way to "escape" them in a safe way? (For example, what if any of them contains single quotes, etc.)

How about not putting spaces in your field names. Seriously.
Ok, if you really must, it should work fine without escaping...
collection.update(MongoDBObject("_id" -> "test"), $set ("with space.a name" -> 2))

There isn't any explicit escaping required for MongoDB; you can just pass a variable name, eg:
val key = MongoDBObject(name + '.' + embeddedname -> "somevalue")
or
val key = MongoDBObject("with space.a name" -> "somevalue")
While MongoDB does allow you to use any valid UTF-8 character in key names aside from '.' and a leading '$', you would generally be best sticking to alphanumeric key names plus underscore.
If you are concerned about safety of user-provided input, see How does MongoDB address SQL or Query injection?

Related

Why single quote escape cannot be used in QuestDB, Error: dangling expression

I'm trying to use Query Variables in Grafana, the panel query source is PostgreSQL for QuestDB.
I have added the variable without any issue, but I'm unable to use the variable in Panel query since the variable values contains the spaces (SENSOR01 ON_OFF), also I'm unable to figure-out how to add single quote escape.
Following are the scenarios I tried:
Scenario1: this indicates due to space in the Variable value, on_off considered as separate word
where sensor_name = $sensor
db query error: pq: unexpected token: on_off
.
.
Scenario2: tried to add single quotes explicitly for the variable value, but there is generic error from source DB (QuestDB)
where sensor_name = concat('''', $sensor, '''')
db query error: pq: dangling expression
When tried Scenario2 approach directly in query of Variable, getting the same error
..
Scenario3: Hard-coded the variable value with space and with single quotes, but this giving me error with first part of the variable, looks like the hard-coded single quotes not passed here!
Error (Scenario3):
Is there any way/workaround to tackle this issue?
Could you just add the quotes directly in the query?
where sensor_name = '$sensor'
I have a similar grafana panel querying a questDB database using a variable and it works for me. This is my query:
select device_type, avg(duration_ms) as avg_duration_ms, avg(speed) as avg_speed, avg(measure1) as avg_m1, avg(measure2) as avg_m2 from ilp_test
WHERE
$__timeFilter(timestamp) and device_type = '$deviceType'
A rather hacky workaround would be to do:
where sensor_name = concat(cast(cast('&' as int) + 1 as char), $sensor, cast(cast('&' as int) + 1 as char))
This should work, but I'm pretty sure there is a better solution. Let me find it and get back to you.
Update. We may support Postgres syntax (which is '' escaping for a single quote char) in one of upcoming versions. For now, you'd have to use the above workaround.

firestore document snapshot get() does not work with dotted string notation of field-names containing hyphen

I've a simple document called 'agents' under a collection named 'mycoll' with data set something like below:
{
'metadata': {
'agent-ids': ['fdfd', 'asdfasdf', 'rerere'],
'agent_ids': ['foo1', 'booo']
}
I got the document snapshot:
snapshot = firestore.client().document('mycoll/agents').get()
If I try to access 'agent-ids' field name using get() method on this snapshot:
agent-list-with-hypens = snapshot.get('metadata.agent-ids')
ValueError: Path metadata.agent-ids not consumed, residue: -ids
However, If I try to access 'agent_ids' using get() method, that works just fine:
print(snapshot.get('metadata.agent_ids'))
['foo1', 'booo']
My question is what is causing this different behavior for field-names with an '-' and why? Any documentation which explains about this? I understand that snapshot.get() accpets a FieldPath argument instead of plain string but existing API documentation does not warn that field-names with an '-' are not allowed in field-path name strings delimited by '.'
In fact, snapshot.get(firestore.client().field_path('metadata', 'agent-ids')) works just fine.
Based on the documentation, here are the constraints on field paths:
Must separate field names with a single period (.)
Must enclose each field name in backticks unless the field name meets the following requirements:
The field name contains only the characters a-z, A-Z, 0-9, and underscore (_)
The field name does not start with 0-9
So a field name/path containing dash will raise ValueError. The above constraints also explain why snapshot.get(firestore.client().field_path('metadata', 'agent-ids')) works just fine is because the field name is enclosed in backticks.

Gremlin: Is there a way to find the character based on the index of a string?

I have vertex "office" and property "name" on OrientDB. I want to find the offices, by name, where the name does not have a "-" as the third character of the string. I imagine this would require some java code within the gremlin query.This is my best attempt, but it is resulting in office names that do in fact have a "-" as their third character.
g.V().hasLabel('office')
.where(values('name').map{it.get().charAt(2)}.is(neq('-')))
.project('Office Name')
.by(values('name'))
Since Gremlin doesn't support String operations (like split, charAt, etc.), your only chance is a lambda. Seems like you figured that out already, but your solution looks too overcomplicated to me. You can use something much simpler, like:
g.V().hasLabel('office').
has('name', filter {it.get()[2] != '-'}).
project('Office Name').
by('name')
However, note, that this filter will throw an exception if the office namer has less than 3 characters. Thus, you should better check that the String is long enough:
g.V().hasLabel('office').
has('name', filter {it.get().length() > 2 && it.get()[2] != '-'}).
project('Office Name').
by('name')
...or use RegEx pattern matching (which is pretty nice and easy in Groovy):
g.V().hasLabel('office').
has('name', filter {it.get() ==~ /.{2}-.*/}).
project('Office Name').
by('name')
The main reason why your traversal didn't work though, is that charAt returns a Character which is then compared to the String -, hence every office name will pass the neq filter.

Insert field name with dot in mongo document

A Meteor server code tries to insert an object into a Mongo collection. The value of one of the property is a string which contains a dot i.e. ".".
Meteor terminal is complaining :-
Error: key Food 1.1 and drinks must not contain '.'
What does this mean and how to fix it?
let obj = {
food: group,
rest: rule,
item: item[0],
key: i
};
FoodCol.insert(obj);
edit
The suggested answer by Kishor for replacing the "." with "\uff0E" will produce a space after the dot which is not what a user expects.
From this link, How to use dot in field name?
You can replace dot symbols of your field name to Unicode equivalent
"\uff0E":
Update: As Fred suggested, please use "\u002E" for "."
We solved this issue by encoding (Base64) the key before insertion and decode after taking out from the db. Since we consume the document as it is and query fields are different and their keys are not encoded.
But if u want to make query using this key or the key should be readable to the user, this solution will be not be suitable.

Casbah/Salat: How to query a field that a part of a string is contained?

i try to write a query with Casbah and Salat to query a field that it includes parts of a name.
I tried to use a regular expression like this (inside a SalatDAO):
val regexp = (""".*"""+serverName+""".*""").r
val query = "serverName" -> regexp
val result = find(MongoDBObject(query))
and with
val regexp = ".*"+serverName+".*"
The record is in MongoDB and when i search it with the complete name it works.
How is the right way to tell casbah to search for a part of the string ?
Another thing that i would like to fix is the string concatenation for the parameter.
Is there any default way to escape input parameters with casbah, so the parameter is not
interpreted as a javascript command ?
Best Regards,
Oliver
In mongodb shell you can find the server names contains the specific string by
db.collection.find({serverName:/whatever/i})
i dont have any experience with casbah, i believe it must be like this. please test
val regexp = ("""/"""+serverName+"""/i""").r
find(MongoDBObject("serverName" -> regexp))