-
Notifications
You must be signed in to change notification settings - Fork 246
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
HSEARCH-4577 @ProjectionConstructor: aggregating multi-valued field/object projections in Set, SortedSet, etc. instead of List #4329
HSEARCH-4577 @ProjectionConstructor: aggregating multi-valued field/object projections in Set, SortedSet, etc. instead of List #4329
Conversation
de93c99
to
c212a42
Compare
c212a42
to
143fd90
Compare
* @return A new step to define optional parameters for the multi-valued projections. | ||
* @see MultiProjectionTypeReference | ||
*/ | ||
<C> FieldProjectionOptionsStep<?, C> multi(MultiProjectionTypeReference<C, T> collectionTypeReference); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder whether renaming this from multi to container and then adding built-in type references for optional is a good idea ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for container
as the default is already "multi", so it feels a bit weird to introduce a "multi".
However, don't we expose "multi" methods in other DSLs, especially in the search DSL? We'd need to be consistent...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah we also have that HighlightProjectionOptionsStep#single()
...
It would be nice if we can just deprecate all that and do something like
.select(
f -> f.composite()
.from(
f.highlight( "anotherString" ), // default list as it is now
f.highlight( "anotherString" ).accumulator(ProjectionAccumulator.single() ), // instead of calling f.highlight( "anotherString" ).single(),
f.highlight( "anotherString" ).accumulator(ProjectionAccumulator.optional() ), // still single but wraps the string into an optional
f.highlight( "anotherString" ).accumulator(ProjectionAccumulator.sortedSet() ), // multi but non-default collection type
f.highlight( "anotherString" ).accumulator(ProjectionAccumulator.sortedSet(customComparator) ), // multi but non-default collection type with custom comparator
f.highlight( "anotherString" ).accumulator(ProjectionAccumulator.array() ), // multi but non-default collection type
f.highlight( "anotherString" ).accumulator(CustomUserDefinedThing.smth() ), // whatever the user came up with
).asList()
)
(well and the same thing in other places: deprecate the multi and give this accumulator as an alternative)
* @param <V> The type of the elements in the collection. | ||
*/ | ||
@Incubating | ||
public interface MultiProjectionTypeReference<C, V> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't come up with a better name for this one .... so any suggestions are more than welcome 😃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't you just promote ProjectionAccumulator
to API, and use ProjectionAccumulator.Provider
? It's admittedly a complex interface, but it's what we use under the hood, and if you provide implementations for the main container types, users will only need to implement it very rarely.
Then you could rename ProjectionAccumulator#single()
to nullable()
and introduce optional()
.
Well, you'll probably need to create a new interface, and juggle with inheritance and deprecations, but you see what I mean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's admittedly a complex interface
yeah ... that's why I was thinking that since we are using this index-based approach for transformation operations in the accumulator that most implementations would still be backed by a list as a temporary storage option and the only difference would be the R finish(A accumulated)
that performs the final transformation. Hence, I thought extracting this method (as convert()
) would work for the users with some custom collections and we'd just delegate to in the list-based accumulator.
but let me see how promoting the accumulator to the API would work out 😃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough, either solution has its merits. I'll let you have a look and decide :)
Hence, I thought extracting this method (as
convert()
) would work for the users with some custom collections and we'd just delegate to in the list-based accumulator.
Note you could also provide a static <V, C> Provider<V, C> simple(Function<List<V>, C> converter)
"factory method" to allow simple list-based implementations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note you could also provide a
static <V, C> Provider<V, C> simple(Function<List<V>, C> converter)
"factory method" to allow simple list-based implementations.
#4334 😀
EDIT: It could probably be generalized to any type of "delegate" accumulator, in particular to allow single-valued simple accumulators, but... this is probably enough?
143fd90
to
7e7e889
Compare
Quality Gate passedIssues Measures |
superseded by #4344 |
https://hibernate.atlassian.net/browse/HSEARCH-4577
for now, just to get a CI run🙈still need more tests, docs and migration guide udpates
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license
and can be relicensed under the terms of the LGPL v2.1 license in the future at the maintainers' discretion.
For more information on licensing, please check here.