-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Provide a typesafe and fluent way to return only a subset of data and to use script_fields #8074
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
Comments
I can help building this feature, if you want. |
Hi @erik-kallen, I have to think about this a little bit more. Currently I only see 1 main problem which would have to be solved in the code-generator:
If that would be the case, you could easily deserialize into a partial type that only has the requested properties marked with This does not solve the problem for meta-fields like the For that transformation part, I'm not sure if we really need a helper, but I'm not completely against adding one. Regarding type safety:
What do you think? |
The problem with the Given that we already have the typesafe ability to generate a Field from an Expression, I don't think it would be a super hard problem to:
The only thing I'm a little worried about is that this means that there is a real risk of the user defining the lambda inline, which would lead to a lot of compilations. To solve this, we could implement expression comparisons and reuse the compiled expressions if the expression trees are identical. Or we could have a limit of how many expressions are allowed to be compiled (which will alert the user to the problem). Or we could not compile the expressions but instead evaluate them dynamically. Actually, I realize that my idea to have the script inline probably won't play well with this cache. Those values probably need to be referenced by some syntax like |
This sounds like a pretty unique problem to be honest. I fully understand the argument about the
The
From the technical side, this is definitely doable and the approach you describe sounds reasonable. However, in the context of this library I'm concerned about using compiled expressions. Besides the actual compilation overhead that you already mentioned, they are interpreted instead of compiled on several platforms like Mono, Xamarin, etc. Even when using AOT compilation in regular .NET framework, expression trees can no longer be compiled. This introduces a significant performance impact on these code pathes.
I've played with expression tree comparison in the past to be able to cache generic EF query results and from my experience, the comparison takes a significant amount of time itself (my code can probably be optimized on a few places) so that it was not worth using for fast queries at all. I can definitely see the value in such helper function and don't want to demotivate you, but the problem you want to solve is really specific in my opinion. I would rather keep the library more generic and don't increase the scope too much. As I'm the only person working on this project, I always have to keep an eye on maintainability as well. This as well was one major reason for switching from hand-crafted code to the code generation approach. Besides that, there are the technical difficulties with the expression trees. If you want to work on this anyways, I would love to see the results, but I don't expect it to be merged upstream at the moment. What I'll definitely add to my list, is to come up with a way to deserialize search query results into a |
I don't understand what you mean. The problem I am referring to is that if I have a
Yes, but as mentioned above, I don't think the TPartialData approach is better than what I currently have.
This is a valid concern. The overload would have to be annotated with RequiresDynamicCode. Or perhaps do whatever EF does (which I don't know the details of, but the problem is very similar).
I don't think it's a very specific problem. Of course, I don't know how other people use the library, but I imagine it not being uncommon for people to do
I understand that, thank you for your work!
I wouldn't mind working on it, but I won't do it if it won't be merged. Or, if it becomes possible to deserialize to a different type than the query builder type, I might implement it as part of my own project (and I can share the code if I manage to get it working nicely).
While I don't see myself using the TPartialData approach, i think I can probably implement what I want externally if TPartialData is allowed to be JsonElement (or JsonNode). |
I understand that concern 🙂 Just the way you want to solve this, is very specific (in my opinon and without knowing all of your requirements). The way I personally would solve this (again, given that we would have a version of the API that allows to specify public record Partial
{
public required int A { get; init; }
public required int B { get; init; }
}
public record Full : Partial
{
public required int C { get; init; }
}
// In the next step, get `Property[]` of `Partial` by reflection and use it to initialize
// the `Fields` instance of the `SourceInclude` property in the `SearchRequest` If this is a suitable class design, of course depends on your needs. And keep in mind, that even with your approach, you would still be forced to update the property names on your already indexed documents, if you rename something. A solution to this would be to use explicit
That definitely could be the case. It's just that from my experience:
Yes, this should be possible in this case. Deserialization to |
Inheritance won't work for me because different queries return different subsets.
Yes, but the main thing I want to do doesn't really have anything to do with the mapping part. It's about reducing the amount of data fetched from elastic, and AutoMapper won't help with that. |
Is your feature request related to a problem? Please describe.
I can't find a good way to return only a subset of the source in a typesafe way. I also can't find a (reasonably) typesafe way to use script_fields.
Describe the solution you'd like
I would like to be able to do this somehow. One option would be a new overload to
SearchAsync
:The intent is that this could be invoked like this:
And this should set the _source_includes and script_fields based on what the factory method wants.
Describe alternatives you've considered
One option is to remove all
required
from my indexed entity and then transform each element in result.Documents.another would be to use
SearchAsync<JsonObject>
, but that doesn't work, either. Trying to use);
results in an exception with this stack trace:
However, using
await client.SearchAsync<Dictionary<string, JsonNode>>(...)
seems to work but is rather unergonomic.The text was updated successfully, but these errors were encountered: