[SERVER-7770] $or should accept a proper object besides "x.y" for embedded-document filtering Created: 27/Nov/12 Updated: 06/Dec/22 Resolved: 24/Jul/19 |
|
| Status: | Closed |
| Project: | Core Server |
| Component/s: | JavaScript, Querying |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Improvement | Priority: | Minor - P4 |
| Reporter: | Cristián | Assignee: | Backlog - Query Team (Inactive) |
| Resolution: | Won't Do | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Assigned Teams: |
Query
|
| Participants: |
| Description |
|
$or accepts as filter an array of objects in the "document.attribute" style, which makes it impossible to build a dynamical query. It should be a proper object in the form of "document: {attribute1: 'value1', attribute2: 'value'}". It seems cleaner, in line with js native form, and also allows to programmatically create a dynamic query (specially if you don't have a fixed set of attributes to search, which seems logical in a schema-less model). |
| Comments |
| Comment by Asya Kamsky [ 24/Jul/19 ] | |||||||||||||
|
We would not be able to change the syntax of query language without breaking existing applications which rely on current semantics. Closing as won't do. | |||||||||||||
| Comment by Stennie Steneker (Inactive) [ 19/Dec/12 ] | |||||||||||||
|
Hi Cristián, My earlier JavaScript example was pushing a custom userInput value into the $or clause. You could build this programatically and would not have to hardcode the key or value.
The syntax you've suggested is already used by dot notation to exactly match a subdocument. If your subdocument contained {{ {"foo": "bar", "bar": "baz"}}} (and in that specific order) you will get a result. So a few further examples: 1) Exact match subdocument against userInput criteria and a subdocument called custom:
2) Build $or clauses with user-provided criteria:
As per the second example, you should be able to build up your query (including subdocument and key names) programatically. Cheers, | |||||||||||||
| Comment by Cristián [ 05/Dec/12 ] | |||||||||||||
|
Hi Stephen, I see your point, but try going back one step and you'll see what I mean: "custom.bar" could be anything, I don't know in advance it could be custom.xxx or custom.yyy.
# customer = { }; userinput = {foo: "bar", bar: "baz"}
query["$or"].push( {custom: userinput})
The db should accept as input: 1. "custom.foo": "bar", "custom.bar": "baz" and 2. "custom": {"foo": "bar", "bar": "baz"}js-wise the second should be the 'proper' way of formatting the object, so the db should be able to read this. but why is it important in my case? because ' {"foo": "bar", "bar": "baz"}' could start as an empty object '{}' and then I can programmatically build it (example: emptyObject[someVar] = someValue) but that's not possible if I'm forced to use "custom.foo": "bar", specially if I don't know what "foo" is in advance (it can be "bar", "baz", "etc".. any value). Cheers, c.
| |||||||||||||
| Comment by Stennie Steneker (Inactive) [ 05/Dec/12 ] | |||||||||||||
|
Hi Cristián, I'm not sure what driver you are using, but if you are building your queries dynamically in your application, you shouldn't have to hard code the "custom.bar" string. You can use a variable to populate your query (and should be properly sanity checking/untainting any user-provided input). For example, in the mongo shell:
Cheers, | |||||||||||||
| Comment by Cristián [ 27/Nov/12 ] | |||||||||||||
|
Sure, here's an example. Let's say I have the following schema in my head: db.customer, where db.customer has an attribute called custom. A representation of a single record could look like this: customer = { }; If want to do an $or query searching for, let's say, custom.bar = "baz", then I can use something like: db.customer.find( { name: "foo bar", $or: [ { "custom.foo": "xyz" }, {"custom.bar": "baz" }] } ) This force me to actually write in my code the string "custom.bar", which is not always possible. Real case? Here's one: I'm writing an app where I let the users dynamically add attributes to the "custom" attribute, so the schema could look like "db.customer.custom.ANYTHING = 'foo bar'". If I'm receiving this attributes and their values in a form of a variable (could come from a db, webform, etc) I can't dynamically write "custom.SOME_KEY = 'SOME_VALUE'", but I could start with an empty object and then add the proper keys an values like "theobject[SOME_KEY] = 'SOME_VALUE'". At least from this case it makes complete sense to be able to pass "custom: {foo: 'bar'}" as an $or filter instead of "custom.foo = 'bar'". Did my best trying to explain, hope it works. | |||||||||||||
| Comment by Eliot Horowitz (Inactive) [ 27/Nov/12 ] | |||||||||||||
|
I'm not sure what you mean exactly. |