-
Notifications
You must be signed in to change notification settings - Fork 440
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
Best practices for search endpoints with multiple criteria #775
Comments
As far as I can tell, once you get to where you need to support arbitrary combinations of parameters, you have to start using querystrings (or something similar) as keys: // router
"searches[{keys:query}][{ranges:index}]" // pathset
['searches', 'foo=bar&baz=qux', { from: 0, to: 19 }] I'd love to hear better ideas though. That's just the best one I've heard so far. |
Take this for what it's worth, but I'm not too fond of the idea of using query strings. To me, the idea of modelling our data on a javascript object is based on predictability (which is how caching and cache-first are able to work). The query string method limits that predictability. For example, in most reasonable implementations, we would treat the order of the query parameters as largely irrelevant. As far as object modelling is concerned, however, these become two different strings. Our application is now responsible for maintaining strict ordering, lest we end up with duplicate data in the cache and unnecessary fetches. Ditto for optional properties: But it's problematic for me too conceptually. We're forcing query-type fetches into an object structure. It would be better, at least conceptually, to remove those kinds of queries from the falcor model entirely. Perhaps with a standard REST endpoint that can return an array of I'd certainly love to hear the Falcor team's thoughts here. I've seen a lot of semi-related comments on other issues. |
I have the same concerns actually, but I think everything you listed is a symptom of the more general anti-pattern of exposing a querying service to the world that allows a combinatorial explosion of possibilities. Expressing that through Falcor merely surfaces the problems with that in Falcor-specific ways. The right thing to do in my view would be to restrict what the world can query down to the smallest possible whitelist of combinations. Falcor can put those known combinations into a graph without resorting to query strings.
|
@greim Totally agreed. For the vast majority of searching use cases, the solution you outlined above is precisely what I'd recommend. However, there are edge cases (particularly in applications that also have intelligence/decision support capabilities) where more sophisticated querying is important. In such cases, assuming Falcor even still makes sense, an external querying service may be the best solution. |
@greim, @joshdmiller What would you do for multiple filters of the same key? {
todosById: {
"44": {
name: "Init",
status: 0
prerequisites: []
},
"54": {
name: "Started",
status: 1
prerequisites: [{ $type: "ref", value: ["todosById", 54] }]
},
"58": {
name: "Paused",
status: 3
prerequisites: [{ $type: "ref", value: ["todosById", 54] }]
},
"64": {
name: "Completed",
status: 2
prerequisites: []
}
},
todos: [
{ $type: "ref", value: ["todosById", 44] },
{ $type: "ref", value: ["todosById", 54] },
{ $type: "ref", value: ["todosById", 58] },
{ $type: "ref", value: ["todosById", 64] }
]
} I would like to get only todos that are either status 0|1. Of course, I wouldn't want to have to create a key for each combination of statuses, especially if I might have 10 different statuses. Maybe using |
The approach I'd prefer is to just expose a bunch of different "keys" on the JSON graph. In the route handler it would then just construct endpoint URLs based on which "key" was matched by the route:
Obviously the caveat is that maybe you couldn't possibly anticipate them all (the afore-mentioned combinatorial explosion) in which case you have to resort to some kind of hack or workaround, as discussed above. |
It's a shame that Falcor distinguishes itself as "not a query language". Search queries are likely to return Falcor already has a syntax for passing parameters. Failing that, querystrings seem like a decent option. It's a standard, and it's something your browser already knows how to do. JSON might work as well if you stringified it. An option that falls more in line with how Falcor wants you to do things is to just not allow for optional fields. Write your full faceted search as one big route and require the client-side code to pass in a value for every facet every time, even if that value is just "ignore me". So lets say you can query on all the fields in the example above, but you decide to omit the city. Your query might look like this: Another option is to parse the query yourself on the server side instead of using the default router. Just establish a rule that keys and values alternate, and you'll be able to handle queries of the form You might even be able to express this inside the standard router by using recursive $refs, but that's probably a silly idea. |
It would be interesting to hear from someone familiar with GraphQL, to see if it has a general-purpose approach for tackling multi-faceted search. Also might be nice if the Falcor core team would officially weigh in on this issue, but yeah I'd expect the answer to echo past statements about why allowing the public to make open-ended queries might be a bad idea. |
I would consider something like: interface Range {
from?: number;
to?: number;
length?: number;
where?: RangeWhere;
order?: RangeOrder;
} where |
Possibly, the issue described here can be solved by addressing a larger issue of being able to pass arguments along with a set of queried paths. That one is tracked in #826 |
I'm currently performing issue triage as we get ready to perform a proper release, and closing/tagging as I go. I've also commented in #826 reinforcing Paul's guidance. Closing. |
This is an extension of #713.
I have a search endpoint that accepts multiple criteria. Not all of them are required. It may look like:
I didn't see where path sets include key-value pairs, so the best I could come up with for the router is:
search[{keys:criteriaKeys}][{keys:criteriaValues}]['name']
An example path:
Is there a best practice for how to search?
The text was updated successfully, but these errors were encountered: