mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-06-28 01:22:26 -04:00
Upgrade to Lucene 9.12.0 (#113333)
This commit upgrades to Lucene 9.12.0. Co-authored-by: Adrien Grand <jpountz@gmail.com> Co-authored-by: Armin Braun <me@obrown.io> Co-authored-by: Benjamin Trent <ben.w.trent@gmail.com> Co-authored-by: Chris Hegarty <chegar999@gmail.com> Co-authored-by: John Wagster <john.wagster@elastic.co> Co-authored-by: Luca Cavanna <javanna@apache.org> Co-authored-by: Mayya Sharipova <mayya.sharipova@elastic.co>
This commit is contained in:
parent
4471e82dcc
commit
32dde26e49
81 changed files with 1435 additions and 350 deletions
|
@ -1,5 +1,5 @@
|
||||||
elasticsearch = 9.0.0
|
elasticsearch = 9.0.0
|
||||||
lucene = 9.11.1
|
lucene = 9.12.0
|
||||||
|
|
||||||
bundled_jdk_vendor = openjdk
|
bundled_jdk_vendor = openjdk
|
||||||
bundled_jdk = 22.0.1+8@c7ec1332f7bb44aeba2eb341ae18aca4
|
bundled_jdk = 22.0.1+8@c7ec1332f7bb44aeba2eb341ae18aca4
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
|
||||||
include::{docs-root}/shared/versions/stack/{source_branch}.asciidoc[]
|
include::{docs-root}/shared/versions/stack/{source_branch}.asciidoc[]
|
||||||
|
|
||||||
:lucene_version: 9.11.1
|
:lucene_version: 9.12.0
|
||||||
:lucene_version_path: 9_11_1
|
:lucene_version_path: 9_12_0
|
||||||
:jdk: 11.0.2
|
:jdk: 11.0.2
|
||||||
:jdk_major: 11
|
:jdk_major: 11
|
||||||
:build_type: tar
|
:build_type: tar
|
||||||
|
|
5
docs/changelog/111465.yaml
Normal file
5
docs/changelog/111465.yaml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
pr: 111465
|
||||||
|
summary: Add range and regexp Intervals
|
||||||
|
area: Search
|
||||||
|
type: enhancement
|
||||||
|
issues: []
|
6
docs/changelog/112826.yaml
Normal file
6
docs/changelog/112826.yaml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
pr: 112826
|
||||||
|
summary: "Multi term intervals: increase max_expansions"
|
||||||
|
area: Search
|
||||||
|
type: enhancement
|
||||||
|
issues:
|
||||||
|
- 110491
|
5
docs/changelog/113333.yaml
Normal file
5
docs/changelog/113333.yaml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
pr: 113333
|
||||||
|
summary: Upgrade to Lucene 9.12
|
||||||
|
area: Search
|
||||||
|
type: upgrade
|
||||||
|
issues: []
|
|
@ -13,16 +13,10 @@ There are several thread pools, but the important ones include:
|
||||||
|
|
||||||
[[search-threadpool]]
|
[[search-threadpool]]
|
||||||
`search`::
|
`search`::
|
||||||
For coordination of count/search operations at the shard level whose computation
|
For count/search operations at the shard level. Used also by fetch and other search
|
||||||
is offloaded to the search_worker thread pool. Used also by fetch and other search
|
|
||||||
related operations Thread pool type is `fixed` with a size of `int((`<<node.processors,
|
related operations Thread pool type is `fixed` with a size of `int((`<<node.processors,
|
||||||
`# of allocated processors`>>`pass:[ * ]3) / 2) + 1`, and queue_size of `1000`.
|
`# of allocated processors`>>`pass:[ * ]3) / 2) + 1`, and queue_size of `1000`.
|
||||||
|
|
||||||
`search_worker`::
|
|
||||||
For the heavy workload of count/search operations that may be executed concurrently
|
|
||||||
across segments within the same shard when possible. Thread pool type is `fixed`
|
|
||||||
with a size of `int((`<<node.processors, `# of allocated processors`>>`pass:[ * ]3) / 2) + 1`, and unbounded queue_size .
|
|
||||||
|
|
||||||
[[search-throttled]]`search_throttled`::
|
[[search-throttled]]`search_throttled`::
|
||||||
For count/search/suggest/get operations on `search_throttled indices`.
|
For count/search/suggest/get operations on `search_throttled indices`.
|
||||||
Thread pool type is `fixed` with a size of `1`, and queue_size of `100`.
|
Thread pool type is `fixed` with a size of `1`, and queue_size of `100`.
|
||||||
|
|
|
@ -73,7 +73,9 @@ Valid rules include:
|
||||||
* <<intervals-match,`match`>>
|
* <<intervals-match,`match`>>
|
||||||
* <<intervals-prefix,`prefix`>>
|
* <<intervals-prefix,`prefix`>>
|
||||||
* <<intervals-wildcard,`wildcard`>>
|
* <<intervals-wildcard,`wildcard`>>
|
||||||
|
* <<intervals-regexp,`regexp`>>
|
||||||
* <<intervals-fuzzy,`fuzzy`>>
|
* <<intervals-fuzzy,`fuzzy`>>
|
||||||
|
* <<intervals-range,`range`>>
|
||||||
* <<intervals-all_of,`all_of`>>
|
* <<intervals-all_of,`all_of`>>
|
||||||
* <<intervals-any_of,`any_of`>>
|
* <<intervals-any_of,`any_of`>>
|
||||||
--
|
--
|
||||||
|
@ -122,8 +124,9 @@ unstemmed ones.
|
||||||
==== `prefix` rule parameters
|
==== `prefix` rule parameters
|
||||||
|
|
||||||
The `prefix` rule matches terms that start with a specified set of characters.
|
The `prefix` rule matches terms that start with a specified set of characters.
|
||||||
This prefix can expand to match at most 128 terms. If the prefix matches more
|
This prefix can expand to match at most `indices.query.bool.max_clause_count`
|
||||||
than 128 terms, {es} returns an error. You can use the
|
<<search-settings,search setting>> terms. If the prefix matches more terms,
|
||||||
|
{es} returns an error. You can use the
|
||||||
<<index-prefixes,`index-prefixes`>> option in the field mapping to avoid this
|
<<index-prefixes,`index-prefixes`>> option in the field mapping to avoid this
|
||||||
limit.
|
limit.
|
||||||
|
|
||||||
|
@ -149,7 +152,8 @@ separate `analyzer` is specified.
|
||||||
==== `wildcard` rule parameters
|
==== `wildcard` rule parameters
|
||||||
|
|
||||||
The `wildcard` rule matches terms using a wildcard pattern. This pattern can
|
The `wildcard` rule matches terms using a wildcard pattern. This pattern can
|
||||||
expand to match at most 128 terms. If the pattern matches more than 128 terms,
|
expand to match at most `indices.query.bool.max_clause_count`
|
||||||
|
<<search-settings,search setting>> terms. If the pattern matches more terms,
|
||||||
{es} returns an error.
|
{es} returns an error.
|
||||||
|
|
||||||
`pattern`::
|
`pattern`::
|
||||||
|
@ -178,12 +182,44 @@ The `pattern` is normalized using the search analyzer from this field, unless
|
||||||
`analyzer` is specified separately.
|
`analyzer` is specified separately.
|
||||||
--
|
--
|
||||||
|
|
||||||
|
[[intervals-regexp]]
|
||||||
|
==== `regexp` rule parameters
|
||||||
|
|
||||||
|
The `regexp` rule matches terms using a regular expression pattern.
|
||||||
|
This pattern can expand to match at most `indices.query.bool.max_clause_count`
|
||||||
|
<<search-settings,search setting>> terms.
|
||||||
|
If the pattern matches more terms,{es} returns an error.
|
||||||
|
|
||||||
|
`pattern`::
|
||||||
|
(Required, string) Regexp pattern used to find matching terms.
|
||||||
|
For a list of operators supported by the
|
||||||
|
`regexp` pattern, see <<regexp-syntax, Regular expression syntax>>.
|
||||||
|
|
||||||
|
WARNING: Avoid using wildcard patterns, such as `.*` or `.*?+``. This can
|
||||||
|
increase the iterations needed to find matching terms and slow search
|
||||||
|
performance.
|
||||||
|
--
|
||||||
|
`analyzer`::
|
||||||
|
(Optional, string) <<analysis, analyzer>> used to normalize the `pattern`.
|
||||||
|
Defaults to the top-level `<field>`'s analyzer.
|
||||||
|
--
|
||||||
|
`use_field`::
|
||||||
|
+
|
||||||
|
--
|
||||||
|
(Optional, string) If specified, match intervals from this field rather than the
|
||||||
|
top-level `<field>`.
|
||||||
|
|
||||||
|
The `pattern` is normalized using the search analyzer from this field, unless
|
||||||
|
`analyzer` is specified separately.
|
||||||
|
--
|
||||||
|
|
||||||
[[intervals-fuzzy]]
|
[[intervals-fuzzy]]
|
||||||
==== `fuzzy` rule parameters
|
==== `fuzzy` rule parameters
|
||||||
|
|
||||||
The `fuzzy` rule matches terms that are similar to the provided term, within an
|
The `fuzzy` rule matches terms that are similar to the provided term, within an
|
||||||
edit distance defined by <<fuzziness>>. If the fuzzy expansion matches more than
|
edit distance defined by <<fuzziness>>. If the fuzzy expansion matches more than
|
||||||
128 terms, {es} returns an error.
|
`indices.query.bool.max_clause_count`
|
||||||
|
<<search-settings,search setting>> terms, {es} returns an error.
|
||||||
|
|
||||||
`term`::
|
`term`::
|
||||||
(Required, string) The term to match
|
(Required, string) The term to match
|
||||||
|
@ -214,6 +250,41 @@ The `term` is normalized using the search analyzer from this field, unless
|
||||||
`analyzer` is specified separately.
|
`analyzer` is specified separately.
|
||||||
--
|
--
|
||||||
|
|
||||||
|
[[intervals-range]]
|
||||||
|
==== `range` rule parameters
|
||||||
|
|
||||||
|
The `range` rule matches terms contained within a provided range.
|
||||||
|
This range can expand to match at most `indices.query.bool.max_clause_count`
|
||||||
|
<<search-settings,search setting>> terms.
|
||||||
|
If the range matches more terms,{es} returns an error.
|
||||||
|
|
||||||
|
`gt`::
|
||||||
|
(Optional, string) Greater than: match terms greater than the provided term.
|
||||||
|
|
||||||
|
`gte`::
|
||||||
|
(Optional, string) Greater than or equal to: match terms greater than or
|
||||||
|
equal to the provided term.
|
||||||
|
|
||||||
|
`lt`::
|
||||||
|
(Optional, string) Less than: match terms less than the provided term.
|
||||||
|
|
||||||
|
`lte`::
|
||||||
|
(Optional, string) Less than or equal to: match terms less than or
|
||||||
|
equal to the provided term.
|
||||||
|
|
||||||
|
NOTE: It is required to provide one of `gt` or `gte` params.
|
||||||
|
It is required to provide one of `lt` or `lte` params.
|
||||||
|
|
||||||
|
|
||||||
|
`analyzer`::
|
||||||
|
(Optional, string) <<analysis, analyzer>> used to normalize the `pattern`.
|
||||||
|
Defaults to the top-level `<field>`'s analyzer.
|
||||||
|
|
||||||
|
`use_field`::
|
||||||
|
(Optional, string) If specified, match intervals from this field rather than the
|
||||||
|
top-level `<field>`.
|
||||||
|
|
||||||
|
|
||||||
[[intervals-all_of]]
|
[[intervals-all_of]]
|
||||||
==== `all_of` rule parameters
|
==== `all_of` rule parameters
|
||||||
|
|
||||||
|
|
|
@ -2814,124 +2814,129 @@
|
||||||
<sha256 value="015d5c229f3cd5c0ebf175c1da08d596d94043362ae9d92637d88848c90537c8" origin="Generated by Gradle"/>
|
<sha256 value="015d5c229f3cd5c0ebf175c1da08d596d94043362ae9d92637d88848c90537c8" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-analysis-common" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-analysis-common" version="9.12.0">
|
||||||
<artifact name="lucene-analysis-common-9.11.1.jar">
|
<artifact name="lucene-analysis-common-9.12.0.jar">
|
||||||
<sha256 value="8dfda34e75bc53906a611bae1b5870b38fd5aa3779a390565da40aa71e98d5d9" origin="Generated by Gradle"/>
|
<sha256 value="8c79d8741f711cc6d7501805b03f7b5f505805d09cab1beb95f0be24b6d27655" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-analysis-icu" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-analysis-icu" version="9.12.0">
|
||||||
<artifact name="lucene-analysis-icu-9.11.1.jar">
|
<artifact name="lucene-analysis-icu-9.12.0.jar">
|
||||||
<sha256 value="caf464abb2cabf9b875dabc0354b43636239170fbe299e103662b267eded136c" origin="Generated by Gradle"/>
|
<sha256 value="52e914cc2d50beec8af0d07f50e5dab803cb9ce8e675ffe43a2aae6102fe6e25" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-analysis-kuromoji" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-analysis-kuromoji" version="9.12.0">
|
||||||
<artifact name="lucene-analysis-kuromoji-9.11.1.jar">
|
<artifact name="lucene-analysis-kuromoji-9.12.0.jar">
|
||||||
<sha256 value="e48721f62cf61ab2084c6ad504194a1bfcf87ba7d3d0274a50466d9a2c5e0f4f" origin="Generated by Gradle"/>
|
<sha256 value="3da0bd68c68cfe518d0e87ea49af1a9560579bca6b9a7fdf642169cb76dd6887" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-analysis-morfologik" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-analysis-morfologik" version="9.12.0">
|
||||||
<artifact name="lucene-analysis-morfologik-9.11.1.jar">
|
<artifact name="lucene-analysis-morfologik-9.12.0.jar">
|
||||||
<sha256 value="ba7f25bcb2face90824d3fe9f9ae6cf258d512b6f2b3810e4a7f68e52261dd97" origin="Generated by Gradle"/>
|
<sha256 value="920358e33d806b5c3feb3566795714e1f36a616520bd2bd5da1e8b639c1f8549" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-analysis-nori" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-analysis-nori" version="9.12.0">
|
||||||
<artifact name="lucene-analysis-nori-9.11.1.jar">
|
<artifact name="lucene-analysis-nori-9.12.0.jar">
|
||||||
<sha256 value="de2092a41c4aeb135e8e240b977dabddf44e558926a836af0c8f3d81b99042dd" origin="Generated by Gradle"/>
|
<sha256 value="26cacbe1d75e138ac0ba1e392edb1877c10a422f98524bf51d5d77492272889d" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-analysis-phonetic" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-analysis-phonetic" version="9.12.0">
|
||||||
<artifact name="lucene-analysis-phonetic-9.11.1.jar">
|
<artifact name="lucene-analysis-phonetic-9.12.0.jar">
|
||||||
<sha256 value="eb769dd82361eb9bc749d7789f45417f62e70ca4551928bece68e01a2978dbaa" origin="Generated by Gradle"/>
|
<sha256 value="4bb24414425e04ccd28c835e8dd7f52259185f8f671aea6432460b4b7afa5cfa" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-analysis-smartcn" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-analysis-smartcn" version="9.12.0">
|
||||||
<artifact name="lucene-analysis-smartcn-9.11.1.jar">
|
<artifact name="lucene-analysis-smartcn-9.12.0.jar">
|
||||||
<sha256 value="d574ad04cf5c0154a3f6d59b5ffcd1428304da5bf16f6f94dd48ebd1c6934f51" origin="Generated by Gradle"/>
|
<sha256 value="ffd68804d3387968784b7f52b7c14c7439fa474ffbf1b36d93fa1d2b04101f7a" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-analysis-stempel" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-analysis-stempel" version="9.12.0">
|
||||||
<artifact name="lucene-analysis-stempel-9.11.1.jar">
|
<artifact name="lucene-analysis-stempel-9.12.0.jar">
|
||||||
<sha256 value="21a96efd877ef74fbd090f95bcc89a3999d703806cf56ac16433812957de6142" origin="Generated by Gradle"/>
|
<sha256 value="c4911b5697c0403b694aa84d3f63090067c74ffa8c95cb088d0b80e91166df4a" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-backward-codecs" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-backward-codecs" version="9.12.0">
|
||||||
<artifact name="lucene-backward-codecs-9.11.1.jar">
|
<artifact name="lucene-backward-codecs-9.12.0.jar">
|
||||||
<sha256 value="d542520817bc9e30b4ece418b36696cfa913425ba6ccdabcb1b5250c08316556" origin="Generated by Gradle"/>
|
<sha256 value="a42c17f304c9bf1e8411ebdcf91baf2df2d00c7bfa13bca9e41ccf381d78cfba" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-codecs" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-codecs" version="9.12.0">
|
||||||
<artifact name="lucene-codecs-9.11.1.jar">
|
<artifact name="lucene-codecs-9.12.0.jar">
|
||||||
<sha256 value="3259aa9e06ea96cfb57b1929eb35a0228da51a334f452b9bbcc8f009eae6dc6d" origin="Generated by Gradle"/>
|
<sha256 value="8173a45b87df23a6dd279916cf16b361c0dcfeff5927121b014d210b19f17555" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-core" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-core" version="9.12.0">
|
||||||
<artifact name="lucene-core-9.11.1.jar">
|
<artifact name="lucene-core-9.12.0.jar">
|
||||||
<sha256 value="cb7a9b121bce4ce054ab690ab43ac13ee11ae516d6cef67650130066beee7c9b" origin="Generated by Gradle"/>
|
<sha256 value="6c7b774b75cd8f369e246f365a47caa54ae991cae6afa49c7f339e9921ca58a0" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-expressions" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-expressions" version="9.12.0">
|
||||||
<artifact name="lucene-expressions-9.11.1.jar">
|
<artifact name="lucene-expressions-9.12.0.jar">
|
||||||
<sha256 value="40637d9b983d4dd004b4e40b1facac6d446e6b85095b2caa499840c6eb62c693" origin="Generated by Gradle"/>
|
<sha256 value="9d14919a3d0f07420c1d57a68de52180ae2477d6255d7f693f44515a4fda9c9b" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-grouping" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-facet" version="9.12.0">
|
||||||
<artifact name="lucene-grouping-9.11.1.jar">
|
<artifact name="lucene-facet-9.12.0.jar">
|
||||||
<sha256 value="53fcb43e1a032001fc5ad207b8bf43d4fa13a88309f21761cb12caa0f61027fb" origin="Generated by Gradle"/>
|
<sha256 value="3c07754f0a1f45ba42a637faa8568c18507defa6b77a1ed71af291cd4e7ac603" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-highlighter" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-grouping" version="9.12.0">
|
||||||
<artifact name="lucene-highlighter-9.11.1.jar">
|
<artifact name="lucene-grouping-9.12.0.jar">
|
||||||
<sha256 value="af91d9a44a6519e6283ec004cf751dbd429018ae80881dd5073b3862fdfd404d" origin="Generated by Gradle"/>
|
<sha256 value="ffc02d047f4f036c5a5f409baaf8e19abca165deccc3e57e7a422560f4de1219" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-join" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-highlighter" version="9.12.0">
|
||||||
<artifact name="lucene-join-9.11.1.jar">
|
<artifact name="lucene-highlighter-9.12.0.jar">
|
||||||
<sha256 value="f2c751e8e1dbc788dc890c25f81930af95fa082f4ced4f977058385c39d92d15" origin="Generated by Gradle"/>
|
<sha256 value="5094e1b38f02eb72500a4283ac0f654e2e81943c5359b629567dd7900c935a59" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-memory" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-join" version="9.12.0">
|
||||||
<artifact name="lucene-memory-9.11.1.jar">
|
<artifact name="lucene-join-9.12.0.jar">
|
||||||
<sha256 value="3ed0343383ae05a27adba87a841856a7c4ff230ae6d3c388d21e49e03c0524de" origin="Generated by Gradle"/>
|
<sha256 value="c49cb1be843295b2c7158c03755f222416fad9915114bc7f74649d20f4fc43d6" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-misc" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-memory" version="9.12.0">
|
||||||
<artifact name="lucene-misc-9.11.1.jar">
|
<artifact name="lucene-memory-9.12.0.jar">
|
||||||
<sha256 value="03dc8018b503fb32e7c0c0e36dbefeaf4cdd20cccf8fb2766b81a383d6963c1b" origin="Generated by Gradle"/>
|
<sha256 value="fdbb9c9b3270ce06370d094f1a80dbbbf81b2638b55fa14cc817469092899f01" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-queries" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-misc" version="9.12.0">
|
||||||
<artifact name="lucene-queries-9.11.1.jar">
|
<artifact name="lucene-misc-9.12.0.jar">
|
||||||
<sha256 value="b3787d26fcadf362f3be77aa4da42ad41e1cf5bf49f040eee731ea95d28acd5a" origin="Generated by Gradle"/>
|
<sha256 value="7989d094b4b168ce9ef2949e13f6bfe820829944e50831881be1adeddbe02c04" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-queryparser" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-queries" version="9.12.0">
|
||||||
<artifact name="lucene-queryparser-9.11.1.jar">
|
<artifact name="lucene-queries-9.12.0.jar">
|
||||||
<sha256 value="63e3f7d0cd7a08975d0cba31d2898de7fa00dc9f3677e37820f4413824538898" origin="Generated by Gradle"/>
|
<sha256 value="3b4da6b1673e4edd141c7b86538cc61f6ff3386106f1f5e179c9fe2d30ea2fca" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-sandbox" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-queryparser" version="9.12.0">
|
||||||
<artifact name="lucene-sandbox-9.11.1.jar">
|
<artifact name="lucene-queryparser-9.12.0.jar">
|
||||||
<sha256 value="a1a9118709d5cc52ca160f439c32280f3ba54ec3ba6e3a0db0c1a73a3d790fdb" origin="Generated by Gradle"/>
|
<sha256 value="fc866b7bbfc199436feb24be7dd5c575445342eb283bfe07dd519eab131d3675" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-spatial-extras" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-sandbox" version="9.12.0">
|
||||||
<artifact name="lucene-spatial-extras-9.11.1.jar">
|
<artifact name="lucene-sandbox-9.12.0.jar">
|
||||||
<sha256 value="72760a0247b64869a27bf754473a67f32374ca3214bf47053f54f716c8666755" origin="Generated by Gradle"/>
|
<sha256 value="2262f39a241f435dba61f230e7528205c34f4bf0008faa57f0808476bb782996" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-spatial3d" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-spatial-extras" version="9.12.0">
|
||||||
<artifact name="lucene-spatial3d-9.11.1.jar">
|
<artifact name="lucene-spatial-extras-9.12.0.jar">
|
||||||
<sha256 value="3e485ee6b2b40898118c87f7b7c9376e8cf787966272aac57e1ef70528e5d7ab" origin="Generated by Gradle"/>
|
<sha256 value="ea41de3b2da573e488033b8b1c2033e17c27ce39957cf6acb8904297ae6e1747" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-suggest" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-spatial3d" version="9.12.0">
|
||||||
<artifact name="lucene-suggest-9.11.1.jar">
|
<artifact name="lucene-spatial3d-9.12.0.jar">
|
||||||
<sha256 value="ce03d7178182694a14ed0433cff532a44b3647cec8d9c1ac541afe7887972105" origin="Generated by Gradle"/>
|
<sha256 value="4263e163937024838a8761618b1ce4eba06857adca0c9385d1ac014ec2937de6" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.lucene" name="lucene-test-framework" version="9.11.1">
|
<component group="org.apache.lucene" name="lucene-suggest" version="9.12.0">
|
||||||
<artifact name="lucene-test-framework-9.11.1.jar">
|
<artifact name="lucene-suggest-9.12.0.jar">
|
||||||
<sha256 value="4a395a7e2a037c49ca869dd9e98693d91ea190c1390de626ccaf83e3afed0811" origin="Generated by Gradle"/>
|
<sha256 value="1606fb9c7cf57d88b2824916c00280c92e14bcde798a6b78b27e0db8f13227f0" origin="Generated by Gradle"/>
|
||||||
|
</artifact>
|
||||||
|
</component>
|
||||||
|
<component group="org.apache.lucene" name="lucene-test-framework" version="9.12.0">
|
||||||
|
<artifact name="lucene-test-framework-9.12.0.jar">
|
||||||
|
<sha256 value="47d4e1f47ebd26117d47af8fbff471c116c571fd7d7bd6cb199d89f8454e5cf0" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="org.apache.maven" name="maven-artifact" version="3.6.1">
|
<component group="org.apache.maven" name="maven-artifact" version="3.6.1">
|
||||||
|
|
|
@ -237,6 +237,8 @@ public class VectorScorerFactoryTests extends AbstractVectorTestCase {
|
||||||
|
|
||||||
try (Directory dir = new MMapDirectory(createTempDir("testRandom"), maxChunkSize)) {
|
try (Directory dir = new MMapDirectory(createTempDir("testRandom"), maxChunkSize)) {
|
||||||
for (var sim : List.of(COSINE, DOT_PRODUCT, EUCLIDEAN, MAXIMUM_INNER_PRODUCT)) {
|
for (var sim : List.of(COSINE, DOT_PRODUCT, EUCLIDEAN, MAXIMUM_INNER_PRODUCT)) {
|
||||||
|
// Use the random supplier for COSINE, which returns values in the normalized range
|
||||||
|
floatArraySupplier = sim == COSINE ? FLOAT_ARRAY_RANDOM_FUNC : floatArraySupplier;
|
||||||
final int dims = randomIntBetween(1, 4096);
|
final int dims = randomIntBetween(1, 4096);
|
||||||
final int size = randomIntBetween(2, 100);
|
final int size = randomIntBetween(2, 100);
|
||||||
final float[][] vectors = new float[size][];
|
final float[][] vectors = new float[size][];
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.apache.lucene.queries.intervals.Intervals;
|
||||||
import org.apache.lucene.queries.intervals.IntervalsSource;
|
import org.apache.lucene.queries.intervals.IntervalsSource;
|
||||||
import org.apache.lucene.search.ConstantScoreQuery;
|
import org.apache.lucene.search.ConstantScoreQuery;
|
||||||
import org.apache.lucene.search.FuzzyQuery;
|
import org.apache.lucene.search.FuzzyQuery;
|
||||||
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||||
import org.apache.lucene.search.MultiTermQuery;
|
import org.apache.lucene.search.MultiTermQuery;
|
||||||
import org.apache.lucene.search.PrefixQuery;
|
import org.apache.lucene.search.PrefixQuery;
|
||||||
|
@ -270,7 +271,11 @@ public class MatchOnlyTextFieldMapper extends FieldMapper {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IntervalsSource prefixIntervals(BytesRef term, SearchExecutionContext context) {
|
public IntervalsSource prefixIntervals(BytesRef term, SearchExecutionContext context) {
|
||||||
return toIntervalsSource(Intervals.prefix(term), new PrefixQuery(new Term(name(), term)), context);
|
return toIntervalsSource(
|
||||||
|
Intervals.prefix(term, IndexSearcher.getMaxClauseCount()),
|
||||||
|
new PrefixQuery(new Term(name(), term)),
|
||||||
|
context
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -285,23 +290,47 @@ public class MatchOnlyTextFieldMapper extends FieldMapper {
|
||||||
new Term(name(), term),
|
new Term(name(), term),
|
||||||
maxDistance,
|
maxDistance,
|
||||||
prefixLength,
|
prefixLength,
|
||||||
128,
|
IndexSearcher.getMaxClauseCount(),
|
||||||
transpositions,
|
transpositions,
|
||||||
MultiTermQuery.CONSTANT_SCORE_BLENDED_REWRITE
|
MultiTermQuery.CONSTANT_SCORE_BLENDED_REWRITE
|
||||||
);
|
);
|
||||||
IntervalsSource fuzzyIntervals = Intervals.multiterm(fuzzyQuery.getAutomata(), term);
|
IntervalsSource fuzzyIntervals = Intervals.multiterm(fuzzyQuery.getAutomata(), IndexSearcher.getMaxClauseCount(), term);
|
||||||
return toIntervalsSource(fuzzyIntervals, fuzzyQuery, context);
|
return toIntervalsSource(fuzzyIntervals, fuzzyQuery, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IntervalsSource wildcardIntervals(BytesRef pattern, SearchExecutionContext context) {
|
public IntervalsSource wildcardIntervals(BytesRef pattern, SearchExecutionContext context) {
|
||||||
return toIntervalsSource(
|
return toIntervalsSource(
|
||||||
Intervals.wildcard(pattern),
|
Intervals.wildcard(pattern, IndexSearcher.getMaxClauseCount()),
|
||||||
new MatchAllDocsQuery(), // wildcard queries can be expensive, what should the approximation be?
|
new MatchAllDocsQuery(), // wildcard queries can be expensive, what should the approximation be?
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntervalsSource regexpIntervals(BytesRef pattern, SearchExecutionContext context) {
|
||||||
|
return toIntervalsSource(
|
||||||
|
Intervals.regexp(pattern, IndexSearcher.getMaxClauseCount()),
|
||||||
|
new MatchAllDocsQuery(), // regexp queries can be expensive, what should the approximation be?
|
||||||
|
context
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntervalsSource rangeIntervals(
|
||||||
|
BytesRef lowerTerm,
|
||||||
|
BytesRef upperTerm,
|
||||||
|
boolean includeLower,
|
||||||
|
boolean includeUpper,
|
||||||
|
SearchExecutionContext context
|
||||||
|
) {
|
||||||
|
return toIntervalsSource(
|
||||||
|
Intervals.range(lowerTerm, upperTerm, includeLower, includeUpper, IndexSearcher.getMaxClauseCount()),
|
||||||
|
new MatchAllDocsQuery(), // range queries can be expensive, what should the approximation be?
|
||||||
|
context
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Query phraseQuery(TokenStream stream, int slop, boolean enablePosIncrements, SearchExecutionContext queryShardContext)
|
public Query phraseQuery(TokenStream stream, int slop, boolean enablePosIncrements, SearchExecutionContext queryShardContext)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import org.apache.lucene.queries.intervals.Intervals;
|
||||||
import org.apache.lucene.queries.intervals.IntervalsSource;
|
import org.apache.lucene.queries.intervals.IntervalsSource;
|
||||||
import org.apache.lucene.search.ConstantScoreQuery;
|
import org.apache.lucene.search.ConstantScoreQuery;
|
||||||
import org.apache.lucene.search.FuzzyQuery;
|
import org.apache.lucene.search.FuzzyQuery;
|
||||||
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.MatchAllDocsQuery;
|
import org.apache.lucene.search.MatchAllDocsQuery;
|
||||||
import org.apache.lucene.search.MultiPhraseQuery;
|
import org.apache.lucene.search.MultiPhraseQuery;
|
||||||
import org.apache.lucene.search.PhraseQuery;
|
import org.apache.lucene.search.PhraseQuery;
|
||||||
|
@ -152,30 +153,56 @@ public class MatchOnlyTextFieldTypeTests extends FieldTypeTestCase {
|
||||||
assertNotEquals(new MatchAllDocsQuery(), SourceConfirmedTextQuery.approximate(delegate));
|
assertNotEquals(new MatchAllDocsQuery(), SourceConfirmedTextQuery.approximate(delegate));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTermIntervals() throws IOException {
|
public void testTermIntervals() {
|
||||||
MappedFieldType ft = new MatchOnlyTextFieldType("field");
|
MappedFieldType ft = new MatchOnlyTextFieldType("field");
|
||||||
IntervalsSource termIntervals = ft.termIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
IntervalsSource termIntervals = ft.termIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
||||||
assertThat(termIntervals, Matchers.instanceOf(SourceIntervalsSource.class));
|
assertThat(termIntervals, Matchers.instanceOf(SourceIntervalsSource.class));
|
||||||
assertEquals(Intervals.term(new BytesRef("foo")), ((SourceIntervalsSource) termIntervals).getIntervalsSource());
|
assertEquals(Intervals.term(new BytesRef("foo")), ((SourceIntervalsSource) termIntervals).getIntervalsSource());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPrefixIntervals() throws IOException {
|
public void testPrefixIntervals() {
|
||||||
MappedFieldType ft = new MatchOnlyTextFieldType("field");
|
MappedFieldType ft = new MatchOnlyTextFieldType("field");
|
||||||
IntervalsSource prefixIntervals = ft.prefixIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
IntervalsSource prefixIntervals = ft.prefixIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
||||||
assertThat(prefixIntervals, Matchers.instanceOf(SourceIntervalsSource.class));
|
assertThat(prefixIntervals, Matchers.instanceOf(SourceIntervalsSource.class));
|
||||||
assertEquals(Intervals.prefix(new BytesRef("foo")), ((SourceIntervalsSource) prefixIntervals).getIntervalsSource());
|
assertEquals(
|
||||||
|
Intervals.prefix(new BytesRef("foo"), IndexSearcher.getMaxClauseCount()),
|
||||||
|
((SourceIntervalsSource) prefixIntervals).getIntervalsSource()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWildcardIntervals() throws IOException {
|
public void testWildcardIntervals() {
|
||||||
MappedFieldType ft = new MatchOnlyTextFieldType("field");
|
MappedFieldType ft = new MatchOnlyTextFieldType("field");
|
||||||
IntervalsSource wildcardIntervals = ft.wildcardIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
IntervalsSource wildcardIntervals = ft.wildcardIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
||||||
assertThat(wildcardIntervals, Matchers.instanceOf(SourceIntervalsSource.class));
|
assertThat(wildcardIntervals, Matchers.instanceOf(SourceIntervalsSource.class));
|
||||||
assertEquals(Intervals.wildcard(new BytesRef("foo")), ((SourceIntervalsSource) wildcardIntervals).getIntervalsSource());
|
assertEquals(
|
||||||
|
Intervals.wildcard(new BytesRef("foo"), IndexSearcher.getMaxClauseCount()),
|
||||||
|
((SourceIntervalsSource) wildcardIntervals).getIntervalsSource()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFuzzyIntervals() throws IOException {
|
public void testRegexpIntervals() {
|
||||||
|
MappedFieldType ft = new MatchOnlyTextFieldType("field");
|
||||||
|
IntervalsSource regexpIntervals = ft.regexpIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
||||||
|
assertThat(regexpIntervals, Matchers.instanceOf(SourceIntervalsSource.class));
|
||||||
|
assertEquals(
|
||||||
|
Intervals.regexp(new BytesRef("foo"), IndexSearcher.getMaxClauseCount()),
|
||||||
|
((SourceIntervalsSource) regexpIntervals).getIntervalsSource()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFuzzyIntervals() {
|
||||||
MappedFieldType ft = new MatchOnlyTextFieldType("field");
|
MappedFieldType ft = new MatchOnlyTextFieldType("field");
|
||||||
IntervalsSource fuzzyIntervals = ft.fuzzyIntervals("foo", 1, 2, true, MOCK_CONTEXT);
|
IntervalsSource fuzzyIntervals = ft.fuzzyIntervals("foo", 1, 2, true, MOCK_CONTEXT);
|
||||||
assertThat(fuzzyIntervals, Matchers.instanceOf(SourceIntervalsSource.class));
|
assertThat(fuzzyIntervals, Matchers.instanceOf(SourceIntervalsSource.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testRangeIntervals() {
|
||||||
|
MappedFieldType ft = new MatchOnlyTextFieldType("field");
|
||||||
|
IntervalsSource rangeIntervals = ft.rangeIntervals(new BytesRef("foo"), new BytesRef("foo1"), true, true, MOCK_CONTEXT);
|
||||||
|
assertThat(rangeIntervals, Matchers.instanceOf(SourceIntervalsSource.class));
|
||||||
|
assertEquals(
|
||||||
|
Intervals.range(new BytesRef("foo"), new BytesRef("foo1"), true, true, IndexSearcher.getMaxClauseCount()),
|
||||||
|
((SourceIntervalsSource) rangeIntervals).getIntervalsSource()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ apply plugin: 'elasticsearch.internal-yaml-rest-test'
|
||||||
|
|
||||||
restResources {
|
restResources {
|
||||||
restApi {
|
restApi {
|
||||||
include '_common', 'bulk', 'count', 'cluster', 'field_caps', 'get', 'knn_search', 'index', 'indices', 'msearch',
|
include 'capabilities', '_common', 'bulk', 'count', 'cluster', 'field_caps', 'get', 'knn_search', 'index', 'indices', 'msearch',
|
||||||
'search', 'async_search', 'graph', '*_point_in_time', 'info', 'scroll', 'clear_scroll', 'search_mvt', 'eql', 'sql'
|
'search', 'async_search', 'graph', '*_point_in_time', 'info', 'scroll', 'clear_scroll', 'search_mvt', 'eql', 'sql'
|
||||||
}
|
}
|
||||||
restTests {
|
restTests {
|
||||||
|
|
|
@ -476,3 +476,53 @@ setup:
|
||||||
- match: { hits.hits.0._id: "6" }
|
- match: { hits.hits.0._id: "6" }
|
||||||
- match: { hits.hits.1._id: "5" }
|
- match: { hits.hits.1._id: "5" }
|
||||||
|
|
||||||
|
---
|
||||||
|
"Test regexp":
|
||||||
|
- requires:
|
||||||
|
capabilities:
|
||||||
|
- method: POST
|
||||||
|
path: /_search
|
||||||
|
capabilities: [ range_regexp_interval_queries ]
|
||||||
|
test_runner_features: capabilities
|
||||||
|
reason: "Support for range and regexp interval queries capability required"
|
||||||
|
- do:
|
||||||
|
search:
|
||||||
|
index: test
|
||||||
|
body:
|
||||||
|
query:
|
||||||
|
intervals:
|
||||||
|
text:
|
||||||
|
all_of:
|
||||||
|
intervals:
|
||||||
|
- match:
|
||||||
|
query: cold
|
||||||
|
- regexp:
|
||||||
|
pattern: ou.*ide
|
||||||
|
- match: { hits.total.value: 3 }
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
"Test range":
|
||||||
|
- requires:
|
||||||
|
capabilities:
|
||||||
|
- method: POST
|
||||||
|
path: /_search
|
||||||
|
capabilities: [ range_regexp_interval_queries ]
|
||||||
|
test_runner_features: capabilities
|
||||||
|
reason: "Support for range and regexp interval queries capability required"
|
||||||
|
- do:
|
||||||
|
search:
|
||||||
|
index: test
|
||||||
|
body:
|
||||||
|
query:
|
||||||
|
intervals:
|
||||||
|
text:
|
||||||
|
all_of:
|
||||||
|
intervals:
|
||||||
|
- match:
|
||||||
|
query: cold
|
||||||
|
- range:
|
||||||
|
gte: out
|
||||||
|
lte: ouu
|
||||||
|
- match: { hits.total.value: 3 }
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ dependencies {
|
||||||
api "org.apache.lucene:lucene-core:${versions.lucene}"
|
api "org.apache.lucene:lucene-core:${versions.lucene}"
|
||||||
api "org.apache.lucene:lucene-analysis-common:${versions.lucene}"
|
api "org.apache.lucene:lucene-analysis-common:${versions.lucene}"
|
||||||
api "org.apache.lucene:lucene-backward-codecs:${versions.lucene}"
|
api "org.apache.lucene:lucene-backward-codecs:${versions.lucene}"
|
||||||
|
api "org.apache.lucene:lucene-facet:${versions.lucene}"
|
||||||
api "org.apache.lucene:lucene-grouping:${versions.lucene}"
|
api "org.apache.lucene:lucene-grouping:${versions.lucene}"
|
||||||
api "org.apache.lucene:lucene-highlighter:${versions.lucene}"
|
api "org.apache.lucene:lucene-highlighter:${versions.lucene}"
|
||||||
api "org.apache.lucene:lucene-join:${versions.lucene}"
|
api "org.apache.lucene:lucene-join:${versions.lucene}"
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.elasticsearch.index.codec.Elasticsearch814Codec;
|
|
||||||
import org.elasticsearch.index.codec.tsdb.ES87TSDBDocValuesFormat;
|
import org.elasticsearch.index.codec.tsdb.ES87TSDBDocValuesFormat;
|
||||||
import org.elasticsearch.plugins.internal.RestExtension;
|
import org.elasticsearch.plugins.internal.RestExtension;
|
||||||
|
|
||||||
|
@ -455,7 +454,10 @@ module org.elasticsearch.server {
|
||||||
org.elasticsearch.index.codec.vectors.ES815HnswBitVectorsFormat,
|
org.elasticsearch.index.codec.vectors.ES815HnswBitVectorsFormat,
|
||||||
org.elasticsearch.index.codec.vectors.ES815BitFlatVectorFormat;
|
org.elasticsearch.index.codec.vectors.ES815BitFlatVectorFormat;
|
||||||
|
|
||||||
provides org.apache.lucene.codecs.Codec with Elasticsearch814Codec;
|
provides org.apache.lucene.codecs.Codec
|
||||||
|
with
|
||||||
|
org.elasticsearch.index.codec.Elasticsearch814Codec,
|
||||||
|
org.elasticsearch.index.codec.Elasticsearch816Codec;
|
||||||
|
|
||||||
provides org.apache.logging.log4j.core.util.ContextDataProvider with org.elasticsearch.common.logging.DynamicContextDataProvider;
|
provides org.apache.logging.log4j.core.util.ContextDataProvider with org.elasticsearch.common.logging.DynamicContextDataProvider;
|
||||||
|
|
||||||
|
|
|
@ -230,6 +230,7 @@ public class TransportVersions {
|
||||||
public static final TransportVersion ADD_DATA_STREAM_OPTIONS = def(8_754_00_0);
|
public static final TransportVersion ADD_DATA_STREAM_OPTIONS = def(8_754_00_0);
|
||||||
public static final TransportVersion CCS_REMOTE_TELEMETRY_STATS = def(8_755_00_0);
|
public static final TransportVersion CCS_REMOTE_TELEMETRY_STATS = def(8_755_00_0);
|
||||||
public static final TransportVersion ESQL_CCS_EXECUTION_INFO = def(8_756_00_0);
|
public static final TransportVersion ESQL_CCS_EXECUTION_INFO = def(8_756_00_0);
|
||||||
|
public static final TransportVersion REGEX_AND_RANGE_INTERVAL_QUERIES = def(8_757_00_0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* STOP! READ THIS FIRST! No, really,
|
* STOP! READ THIS FIRST! No, really,
|
||||||
|
|
|
@ -13,6 +13,7 @@ import org.apache.logging.log4j.Logger;
|
||||||
import org.apache.lucene.backward_codecs.lucene50.Lucene50PostingsFormat;
|
import org.apache.lucene.backward_codecs.lucene50.Lucene50PostingsFormat;
|
||||||
import org.apache.lucene.backward_codecs.lucene84.Lucene84PostingsFormat;
|
import org.apache.lucene.backward_codecs.lucene84.Lucene84PostingsFormat;
|
||||||
import org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat;
|
import org.apache.lucene.backward_codecs.lucene90.Lucene90PostingsFormat;
|
||||||
|
import org.apache.lucene.backward_codecs.lucene99.Lucene99PostingsFormat;
|
||||||
import org.apache.lucene.codecs.DocValuesProducer;
|
import org.apache.lucene.codecs.DocValuesProducer;
|
||||||
import org.apache.lucene.codecs.FieldsProducer;
|
import org.apache.lucene.codecs.FieldsProducer;
|
||||||
import org.apache.lucene.codecs.KnnVectorsReader;
|
import org.apache.lucene.codecs.KnnVectorsReader;
|
||||||
|
@ -20,7 +21,7 @@ import org.apache.lucene.codecs.NormsProducer;
|
||||||
import org.apache.lucene.codecs.PointsReader;
|
import org.apache.lucene.codecs.PointsReader;
|
||||||
import org.apache.lucene.codecs.StoredFieldsReader;
|
import org.apache.lucene.codecs.StoredFieldsReader;
|
||||||
import org.apache.lucene.codecs.TermVectorsReader;
|
import org.apache.lucene.codecs.TermVectorsReader;
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat;
|
import org.apache.lucene.codecs.lucene912.Lucene912PostingsFormat;
|
||||||
import org.apache.lucene.index.BinaryDocValues;
|
import org.apache.lucene.index.BinaryDocValues;
|
||||||
import org.apache.lucene.index.ByteVectorValues;
|
import org.apache.lucene.index.ByteVectorValues;
|
||||||
import org.apache.lucene.index.DirectoryReader;
|
import org.apache.lucene.index.DirectoryReader;
|
||||||
|
@ -304,6 +305,9 @@ final class IndexDiskUsageAnalyzer {
|
||||||
private static BlockTermState getBlockTermState(TermsEnum termsEnum, BytesRef term) throws IOException {
|
private static BlockTermState getBlockTermState(TermsEnum termsEnum, BytesRef term) throws IOException {
|
||||||
if (term != null && termsEnum.seekExact(term)) {
|
if (term != null && termsEnum.seekExact(term)) {
|
||||||
final TermState termState = termsEnum.termState();
|
final TermState termState = termsEnum.termState();
|
||||||
|
if (termState instanceof final Lucene912PostingsFormat.IntBlockTermState blockTermState) {
|
||||||
|
return new BlockTermState(blockTermState.docStartFP, blockTermState.posStartFP, blockTermState.payStartFP);
|
||||||
|
}
|
||||||
if (termState instanceof final ES812PostingsFormat.IntBlockTermState blockTermState) {
|
if (termState instanceof final ES812PostingsFormat.IntBlockTermState blockTermState) {
|
||||||
return new BlockTermState(blockTermState.docStartFP, blockTermState.posStartFP, blockTermState.payStartFP);
|
return new BlockTermState(blockTermState.docStartFP, blockTermState.posStartFP, blockTermState.payStartFP);
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Lucene {
|
public class Lucene {
|
||||||
public static final String LATEST_CODEC = "Lucene99";
|
public static final String LATEST_CODEC = "Lucene912";
|
||||||
|
|
||||||
public static final String SOFT_DELETES_FIELD = "__soft_deletes";
|
public static final String SOFT_DELETES_FIELD = "__soft_deletes";
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ public class Lucene {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object doBody(String segmentFileName) throws IOException {
|
protected Object doBody(String segmentFileName) throws IOException {
|
||||||
try (IndexInput input = directory.openInput(segmentFileName, IOContext.READ)) {
|
try (IndexInput input = directory.openInput(segmentFileName, IOContext.READONCE)) {
|
||||||
CodecUtil.checksumEntireFile(input);
|
CodecUtil.checksumEntireFile(input);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -116,6 +116,7 @@ public class IndexVersions {
|
||||||
public static final IndexVersion LENIENT_UPDATEABLE_SYNONYMS = def(8_513_00_0, Version.LUCENE_9_11_1);
|
public static final IndexVersion LENIENT_UPDATEABLE_SYNONYMS = def(8_513_00_0, Version.LUCENE_9_11_1);
|
||||||
public static final IndexVersion ENABLE_IGNORE_MALFORMED_LOGSDB = def(8_514_00_0, Version.LUCENE_9_11_1);
|
public static final IndexVersion ENABLE_IGNORE_MALFORMED_LOGSDB = def(8_514_00_0, Version.LUCENE_9_11_1);
|
||||||
public static final IndexVersion MERGE_ON_RECOVERY_VERSION = def(8_515_00_0, Version.LUCENE_9_11_1);
|
public static final IndexVersion MERGE_ON_RECOVERY_VERSION = def(8_515_00_0, Version.LUCENE_9_11_1);
|
||||||
|
public static final IndexVersion UPGRADE_TO_LUCENE_9_12 = def(8_516_00_0, Version.LUCENE_9_12_0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* STOP! READ THIS FIRST! No, really,
|
* STOP! READ THIS FIRST! No, really,
|
||||||
|
|
|
@ -12,7 +12,7 @@ package org.elasticsearch.index.codec;
|
||||||
import org.apache.lucene.codecs.Codec;
|
import org.apache.lucene.codecs.Codec;
|
||||||
import org.apache.lucene.codecs.FieldInfosFormat;
|
import org.apache.lucene.codecs.FieldInfosFormat;
|
||||||
import org.apache.lucene.codecs.FilterCodec;
|
import org.apache.lucene.codecs.FilterCodec;
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99Codec;
|
import org.apache.lucene.codecs.lucene912.Lucene912Codec;
|
||||||
import org.elasticsearch.common.util.BigArrays;
|
import org.elasticsearch.common.util.BigArrays;
|
||||||
import org.elasticsearch.common.util.FeatureFlag;
|
import org.elasticsearch.common.util.FeatureFlag;
|
||||||
import org.elasticsearch.core.Nullable;
|
import org.elasticsearch.core.Nullable;
|
||||||
|
@ -46,7 +46,7 @@ public class CodecService implements CodecProvider {
|
||||||
public CodecService(@Nullable MapperService mapperService, BigArrays bigArrays) {
|
public CodecService(@Nullable MapperService mapperService, BigArrays bigArrays) {
|
||||||
final var codecs = new HashMap<String, Codec>();
|
final var codecs = new HashMap<String, Codec>();
|
||||||
|
|
||||||
Codec legacyBestSpeedCodec = new LegacyPerFieldMapperCodec(Lucene99Codec.Mode.BEST_SPEED, mapperService, bigArrays);
|
Codec legacyBestSpeedCodec = new LegacyPerFieldMapperCodec(Lucene912Codec.Mode.BEST_SPEED, mapperService, bigArrays);
|
||||||
if (ZSTD_STORED_FIELDS_FEATURE_FLAG.isEnabled()) {
|
if (ZSTD_STORED_FIELDS_FEATURE_FLAG.isEnabled()) {
|
||||||
codecs.put(DEFAULT_CODEC, new PerFieldMapperCodec(Zstd814StoredFieldsFormat.Mode.BEST_SPEED, mapperService, bigArrays));
|
codecs.put(DEFAULT_CODEC, new PerFieldMapperCodec(Zstd814StoredFieldsFormat.Mode.BEST_SPEED, mapperService, bigArrays));
|
||||||
} else {
|
} else {
|
||||||
|
@ -58,7 +58,7 @@ public class CodecService implements CodecProvider {
|
||||||
BEST_COMPRESSION_CODEC,
|
BEST_COMPRESSION_CODEC,
|
||||||
new PerFieldMapperCodec(Zstd814StoredFieldsFormat.Mode.BEST_COMPRESSION, mapperService, bigArrays)
|
new PerFieldMapperCodec(Zstd814StoredFieldsFormat.Mode.BEST_COMPRESSION, mapperService, bigArrays)
|
||||||
);
|
);
|
||||||
Codec legacyBestCompressionCodec = new LegacyPerFieldMapperCodec(Lucene99Codec.Mode.BEST_COMPRESSION, mapperService, bigArrays);
|
Codec legacyBestCompressionCodec = new LegacyPerFieldMapperCodec(Lucene912Codec.Mode.BEST_COMPRESSION, mapperService, bigArrays);
|
||||||
codecs.put(LEGACY_BEST_COMPRESSION_CODEC, legacyBestCompressionCodec);
|
codecs.put(LEGACY_BEST_COMPRESSION_CODEC, legacyBestCompressionCodec);
|
||||||
|
|
||||||
codecs.put(LUCENE_DEFAULT_CODEC, Codec.getDefault());
|
codecs.put(LUCENE_DEFAULT_CODEC, Codec.getDefault());
|
||||||
|
|
|
@ -9,14 +9,14 @@
|
||||||
|
|
||||||
package org.elasticsearch.index.codec;
|
package org.elasticsearch.index.codec;
|
||||||
|
|
||||||
|
import org.apache.lucene.backward_codecs.lucene99.Lucene99Codec;
|
||||||
|
import org.apache.lucene.backward_codecs.lucene99.Lucene99PostingsFormat;
|
||||||
import org.apache.lucene.codecs.DocValuesFormat;
|
import org.apache.lucene.codecs.DocValuesFormat;
|
||||||
import org.apache.lucene.codecs.KnnVectorsFormat;
|
import org.apache.lucene.codecs.KnnVectorsFormat;
|
||||||
import org.apache.lucene.codecs.PostingsFormat;
|
import org.apache.lucene.codecs.PostingsFormat;
|
||||||
import org.apache.lucene.codecs.StoredFieldsFormat;
|
import org.apache.lucene.codecs.StoredFieldsFormat;
|
||||||
import org.apache.lucene.codecs.lucene90.Lucene90DocValuesFormat;
|
import org.apache.lucene.codecs.lucene90.Lucene90DocValuesFormat;
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99Codec;
|
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99HnswVectorsFormat;
|
import org.apache.lucene.codecs.lucene99.Lucene99HnswVectorsFormat;
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99PostingsFormat;
|
|
||||||
import org.apache.lucene.codecs.perfield.PerFieldDocValuesFormat;
|
import org.apache.lucene.codecs.perfield.PerFieldDocValuesFormat;
|
||||||
import org.apache.lucene.codecs.perfield.PerFieldKnnVectorsFormat;
|
import org.apache.lucene.codecs.perfield.PerFieldKnnVectorsFormat;
|
||||||
import org.apache.lucene.codecs.perfield.PerFieldPostingsFormat;
|
import org.apache.lucene.codecs.perfield.PerFieldPostingsFormat;
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the "Elastic License
|
||||||
|
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||||
|
* Public License v 1"; you may not use this file except in compliance with, at
|
||||||
|
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||||
|
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.index.codec;
|
||||||
|
|
||||||
|
import org.apache.lucene.codecs.DocValuesFormat;
|
||||||
|
import org.apache.lucene.codecs.KnnVectorsFormat;
|
||||||
|
import org.apache.lucene.codecs.PostingsFormat;
|
||||||
|
import org.apache.lucene.codecs.StoredFieldsFormat;
|
||||||
|
import org.apache.lucene.codecs.lucene90.Lucene90DocValuesFormat;
|
||||||
|
import org.apache.lucene.codecs.lucene912.Lucene912Codec;
|
||||||
|
import org.apache.lucene.codecs.lucene912.Lucene912PostingsFormat;
|
||||||
|
import org.apache.lucene.codecs.lucene99.Lucene99HnswVectorsFormat;
|
||||||
|
import org.apache.lucene.codecs.perfield.PerFieldDocValuesFormat;
|
||||||
|
import org.apache.lucene.codecs.perfield.PerFieldKnnVectorsFormat;
|
||||||
|
import org.apache.lucene.codecs.perfield.PerFieldPostingsFormat;
|
||||||
|
import org.elasticsearch.index.codec.zstd.Zstd814StoredFieldsFormat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Elasticsearch codec as of 8.16. This extends the Lucene 9.12 codec to compressed stored fields with ZSTD instead of LZ4/DEFLATE. See
|
||||||
|
* {@link Zstd814StoredFieldsFormat}.
|
||||||
|
*/
|
||||||
|
public class Elasticsearch816Codec extends CodecService.DeduplicateFieldInfosCodec {
|
||||||
|
|
||||||
|
private final StoredFieldsFormat storedFieldsFormat;
|
||||||
|
|
||||||
|
private final PostingsFormat defaultPostingsFormat;
|
||||||
|
private final PostingsFormat postingsFormat = new PerFieldPostingsFormat() {
|
||||||
|
@Override
|
||||||
|
public PostingsFormat getPostingsFormatForField(String field) {
|
||||||
|
return Elasticsearch816Codec.this.getPostingsFormatForField(field);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final DocValuesFormat defaultDVFormat;
|
||||||
|
private final DocValuesFormat docValuesFormat = new PerFieldDocValuesFormat() {
|
||||||
|
@Override
|
||||||
|
public DocValuesFormat getDocValuesFormatForField(String field) {
|
||||||
|
return Elasticsearch816Codec.this.getDocValuesFormatForField(field);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private final KnnVectorsFormat defaultKnnVectorsFormat;
|
||||||
|
private final KnnVectorsFormat knnVectorsFormat = new PerFieldKnnVectorsFormat() {
|
||||||
|
@Override
|
||||||
|
public KnnVectorsFormat getKnnVectorsFormatForField(String field) {
|
||||||
|
return Elasticsearch816Codec.this.getKnnVectorsFormatForField(field);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Public no-arg constructor, needed for SPI loading at read-time. */
|
||||||
|
public Elasticsearch816Codec() {
|
||||||
|
this(Zstd814StoredFieldsFormat.Mode.BEST_SPEED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor. Takes a {@link Zstd814StoredFieldsFormat.Mode} that describes whether to optimize for retrieval speed at the expense of
|
||||||
|
* worse space-efficiency or vice-versa.
|
||||||
|
*/
|
||||||
|
public Elasticsearch816Codec(Zstd814StoredFieldsFormat.Mode mode) {
|
||||||
|
super("Elasticsearch816", new Lucene912Codec());
|
||||||
|
this.storedFieldsFormat = new Zstd814StoredFieldsFormat(mode);
|
||||||
|
this.defaultPostingsFormat = new Lucene912PostingsFormat();
|
||||||
|
this.defaultDVFormat = new Lucene90DocValuesFormat();
|
||||||
|
this.defaultKnnVectorsFormat = new Lucene99HnswVectorsFormat();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StoredFieldsFormat storedFieldsFormat() {
|
||||||
|
return storedFieldsFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final PostingsFormat postingsFormat() {
|
||||||
|
return postingsFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final DocValuesFormat docValuesFormat() {
|
||||||
|
return docValuesFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final KnnVectorsFormat knnVectorsFormat() {
|
||||||
|
return knnVectorsFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the postings format that should be used for writing new segments of <code>field</code>.
|
||||||
|
*
|
||||||
|
* <p>The default implementation always returns "Lucene912".
|
||||||
|
*
|
||||||
|
* <p><b>WARNING:</b> if you subclass, you are responsible for index backwards compatibility:
|
||||||
|
* future version of Lucene are only guaranteed to be able to read the default implementation,
|
||||||
|
*/
|
||||||
|
public PostingsFormat getPostingsFormatForField(String field) {
|
||||||
|
return defaultPostingsFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the docvalues format that should be used for writing new segments of <code>field</code>
|
||||||
|
* .
|
||||||
|
*
|
||||||
|
* <p>The default implementation always returns "Lucene912".
|
||||||
|
*
|
||||||
|
* <p><b>WARNING:</b> if you subclass, you are responsible for index backwards compatibility:
|
||||||
|
* future version of Lucene are only guaranteed to be able to read the default implementation.
|
||||||
|
*/
|
||||||
|
public DocValuesFormat getDocValuesFormatForField(String field) {
|
||||||
|
return defaultDVFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the vectors format that should be used for writing new segments of <code>field</code>
|
||||||
|
*
|
||||||
|
* <p>The default implementation always returns "Lucene912".
|
||||||
|
*
|
||||||
|
* <p><b>WARNING:</b> if you subclass, you are responsible for index backwards compatibility:
|
||||||
|
* future version of Lucene are only guaranteed to be able to read the default implementation.
|
||||||
|
*/
|
||||||
|
public KnnVectorsFormat getKnnVectorsFormatForField(String field) {
|
||||||
|
return defaultKnnVectorsFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ import org.apache.lucene.codecs.Codec;
|
||||||
import org.apache.lucene.codecs.DocValuesFormat;
|
import org.apache.lucene.codecs.DocValuesFormat;
|
||||||
import org.apache.lucene.codecs.KnnVectorsFormat;
|
import org.apache.lucene.codecs.KnnVectorsFormat;
|
||||||
import org.apache.lucene.codecs.PostingsFormat;
|
import org.apache.lucene.codecs.PostingsFormat;
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99Codec;
|
import org.apache.lucene.codecs.lucene912.Lucene912Codec;
|
||||||
import org.elasticsearch.common.lucene.Lucene;
|
import org.elasticsearch.common.lucene.Lucene;
|
||||||
import org.elasticsearch.common.util.BigArrays;
|
import org.elasticsearch.common.util.BigArrays;
|
||||||
import org.elasticsearch.index.mapper.MapperService;
|
import org.elasticsearch.index.mapper.MapperService;
|
||||||
|
@ -22,11 +22,11 @@ import org.elasticsearch.index.mapper.MapperService;
|
||||||
* Legacy version of {@link PerFieldMapperCodec}. This codec is preserved to give an escape hatch in case we encounter issues with new
|
* Legacy version of {@link PerFieldMapperCodec}. This codec is preserved to give an escape hatch in case we encounter issues with new
|
||||||
* changes in {@link PerFieldMapperCodec}.
|
* changes in {@link PerFieldMapperCodec}.
|
||||||
*/
|
*/
|
||||||
public final class LegacyPerFieldMapperCodec extends Lucene99Codec {
|
public final class LegacyPerFieldMapperCodec extends Lucene912Codec {
|
||||||
|
|
||||||
private final PerFieldFormatSupplier formatSupplier;
|
private final PerFieldFormatSupplier formatSupplier;
|
||||||
|
|
||||||
public LegacyPerFieldMapperCodec(Lucene99Codec.Mode compressionMode, MapperService mapperService, BigArrays bigArrays) {
|
public LegacyPerFieldMapperCodec(Lucene912Codec.Mode compressionMode, MapperService mapperService, BigArrays bigArrays) {
|
||||||
super(compressionMode);
|
super(compressionMode);
|
||||||
this.formatSupplier = new PerFieldFormatSupplier(mapperService, bigArrays);
|
this.formatSupplier = new PerFieldFormatSupplier(mapperService, bigArrays);
|
||||||
// If the below assertion fails, it is a sign that Lucene released a new codec. You must create a copy of the current Elasticsearch
|
// If the below assertion fails, it is a sign that Lucene released a new codec. You must create a copy of the current Elasticsearch
|
||||||
|
|
|
@ -26,7 +26,7 @@ import org.elasticsearch.index.mapper.MapperService;
|
||||||
* per index in real time via the mapping API. If no specific postings format or vector format is
|
* per index in real time via the mapping API. If no specific postings format or vector format is
|
||||||
* configured for a specific field the default postings or vector format is used.
|
* configured for a specific field the default postings or vector format is used.
|
||||||
*/
|
*/
|
||||||
public final class PerFieldMapperCodec extends Elasticsearch814Codec {
|
public final class PerFieldMapperCodec extends Elasticsearch816Codec {
|
||||||
|
|
||||||
private final PerFieldFormatSupplier formatSupplier;
|
private final PerFieldFormatSupplier formatSupplier;
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class ES813FlatVectorFormat extends KnnVectorsFormat {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KnnFieldVectorsWriter<?> addField(FieldInfo fieldInfo) throws IOException {
|
public KnnFieldVectorsWriter<?> addField(FieldInfo fieldInfo) throws IOException {
|
||||||
return writer.addField(fieldInfo, null);
|
return writer.addField(fieldInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class ES813Int8FlatVectorFormat extends KnnVectorsFormat {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KnnFieldVectorsWriter<?> addField(FieldInfo fieldInfo) throws IOException {
|
public KnnFieldVectorsWriter<?> addField(FieldInfo fieldInfo) throws IOException {
|
||||||
return writer.addField(fieldInfo, null);
|
return writer.addField(fieldInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
package org.elasticsearch.index.codec.vectors;
|
package org.elasticsearch.index.codec.vectors;
|
||||||
|
|
||||||
import org.apache.lucene.codecs.KnnFieldVectorsWriter;
|
|
||||||
import org.apache.lucene.codecs.hnsw.DefaultFlatVectorScorer;
|
import org.apache.lucene.codecs.hnsw.DefaultFlatVectorScorer;
|
||||||
import org.apache.lucene.codecs.hnsw.FlatFieldVectorsWriter;
|
import org.apache.lucene.codecs.hnsw.FlatFieldVectorsWriter;
|
||||||
import org.apache.lucene.codecs.hnsw.FlatVectorsFormat;
|
import org.apache.lucene.codecs.hnsw.FlatVectorsFormat;
|
||||||
|
@ -67,6 +66,7 @@ public class ES814ScalarQuantizedVectorsFormat extends FlatVectorsFormat {
|
||||||
private final boolean compress;
|
private final boolean compress;
|
||||||
|
|
||||||
public ES814ScalarQuantizedVectorsFormat(Float confidenceInterval, int bits, boolean compress) {
|
public ES814ScalarQuantizedVectorsFormat(Float confidenceInterval, int bits, boolean compress) {
|
||||||
|
super(NAME);
|
||||||
if (confidenceInterval != null
|
if (confidenceInterval != null
|
||||||
&& confidenceInterval != DYNAMIC_CONFIDENCE_INTERVAL
|
&& confidenceInterval != DYNAMIC_CONFIDENCE_INTERVAL
|
||||||
&& (confidenceInterval < MINIMUM_CONFIDENCE_INTERVAL || confidenceInterval > MAXIMUM_CONFIDENCE_INTERVAL)) {
|
&& (confidenceInterval < MINIMUM_CONFIDENCE_INTERVAL || confidenceInterval > MAXIMUM_CONFIDENCE_INTERVAL)) {
|
||||||
|
@ -137,8 +137,8 @@ public class ES814ScalarQuantizedVectorsFormat extends FlatVectorsFormat {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FlatFieldVectorsWriter<?> addField(FieldInfo fieldInfo, KnnFieldVectorsWriter<?> knnFieldVectorsWriter) throws IOException {
|
public FlatFieldVectorsWriter<?> addField(FieldInfo fieldInfo) throws IOException {
|
||||||
return delegate.addField(fieldInfo, knnFieldVectorsWriter);
|
return delegate.addField(fieldInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -29,6 +29,10 @@ class ES815BitFlatVectorsFormat extends FlatVectorsFormat {
|
||||||
|
|
||||||
private final FlatVectorsFormat delegate = new Lucene99FlatVectorsFormat(FlatBitVectorScorer.INSTANCE);
|
private final FlatVectorsFormat delegate = new Lucene99FlatVectorsFormat(FlatBitVectorScorer.INSTANCE);
|
||||||
|
|
||||||
|
protected ES815BitFlatVectorsFormat() {
|
||||||
|
super("ES815BitFlatVectorsFormat");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FlatVectorsWriter fieldsWriter(SegmentWriteState segmentWriteState) throws IOException {
|
public FlatVectorsWriter fieldsWriter(SegmentWriteState segmentWriteState) throws IOException {
|
||||||
return delegate.fieldsWriter(segmentWriteState);
|
return delegate.fieldsWriter(segmentWriteState);
|
||||||
|
|
|
@ -345,7 +345,7 @@ public class CompletionFieldMapper extends FieldMapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
static PostingsFormat postingsFormat() {
|
static PostingsFormat postingsFormat() {
|
||||||
return PostingsFormat.forName("Completion99");
|
return PostingsFormat.forName("Completion912");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -440,6 +440,30 @@ public abstract class MappedFieldType {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a regexp {@link IntervalsSource} for the given pattern.
|
||||||
|
*/
|
||||||
|
public IntervalsSource regexpIntervals(BytesRef pattern, SearchExecutionContext context) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Can only use interval queries on text fields - not on [" + name + "] which is of type [" + typeName() + "]"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a range {@link IntervalsSource} for the given ranges
|
||||||
|
*/
|
||||||
|
public IntervalsSource rangeIntervals(
|
||||||
|
BytesRef lowerTerm,
|
||||||
|
BytesRef upperTerm,
|
||||||
|
boolean includeLower,
|
||||||
|
boolean includeUpper,
|
||||||
|
SearchExecutionContext context
|
||||||
|
) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Can only use interval queries on text fields - not on [" + name + "] which is of type [" + typeName() + "]"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An enum used to describe the relation between the range of terms in a
|
* An enum used to describe the relation between the range of terms in a
|
||||||
* shard when compared with a query range
|
* shard when compared with a query range
|
||||||
|
|
|
@ -248,6 +248,22 @@ public class PlaceHolderFieldMapper extends FieldMapper {
|
||||||
throw new QueryShardException(context, fail("wildcard intervals query"));
|
throw new QueryShardException(context, fail("wildcard intervals query"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntervalsSource regexpIntervals(BytesRef pattern, SearchExecutionContext context) {
|
||||||
|
throw new QueryShardException(context, fail("regexp intervals query"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntervalsSource rangeIntervals(
|
||||||
|
BytesRef lowerTerm,
|
||||||
|
BytesRef upperTerm,
|
||||||
|
boolean includeLower,
|
||||||
|
boolean includeUpper,
|
||||||
|
SearchExecutionContext context
|
||||||
|
) {
|
||||||
|
throw new QueryShardException(context, fail("range intervals query"));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IndexFieldData.Builder fielddataBuilder(FieldDataContext fieldDataContext) {
|
public IndexFieldData.Builder fielddataBuilder(FieldDataContext fieldDataContext) {
|
||||||
throw new IllegalArgumentException(fail("aggregation or sorts"));
|
throw new IllegalArgumentException(fail("aggregation or sorts"));
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.apache.lucene.search.BooleanClause;
|
||||||
import org.apache.lucene.search.BooleanQuery;
|
import org.apache.lucene.search.BooleanQuery;
|
||||||
import org.apache.lucene.search.ConstantScoreQuery;
|
import org.apache.lucene.search.ConstantScoreQuery;
|
||||||
import org.apache.lucene.search.FuzzyQuery;
|
import org.apache.lucene.search.FuzzyQuery;
|
||||||
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.MultiPhraseQuery;
|
import org.apache.lucene.search.MultiPhraseQuery;
|
||||||
import org.apache.lucene.search.MultiTermQuery;
|
import org.apache.lucene.search.MultiTermQuery;
|
||||||
import org.apache.lucene.search.PhraseQuery;
|
import org.apache.lucene.search.PhraseQuery;
|
||||||
|
@ -620,7 +621,10 @@ public final class TextFieldMapper extends FieldMapper {
|
||||||
return Intervals.fixField(name(), Intervals.term(term));
|
return Intervals.fixField(name(), Intervals.term(term));
|
||||||
}
|
}
|
||||||
String wildcardTerm = term.utf8ToString() + "?".repeat(Math.max(0, minChars - term.length));
|
String wildcardTerm = term.utf8ToString() + "?".repeat(Math.max(0, minChars - term.length));
|
||||||
return Intervals.or(Intervals.fixField(name(), Intervals.wildcard(new BytesRef(wildcardTerm))), Intervals.term(term));
|
return Intervals.or(
|
||||||
|
Intervals.fixField(name(), Intervals.wildcard(new BytesRef(wildcardTerm), IndexSearcher.getMaxClauseCount())),
|
||||||
|
Intervals.term(term)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -822,7 +826,7 @@ public final class TextFieldMapper extends FieldMapper {
|
||||||
if (prefixFieldType != null) {
|
if (prefixFieldType != null) {
|
||||||
return prefixFieldType.intervals(term);
|
return prefixFieldType.intervals(term);
|
||||||
}
|
}
|
||||||
return Intervals.prefix(term);
|
return Intervals.prefix(term, IndexSearcher.getMaxClauseCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -836,8 +840,14 @@ public final class TextFieldMapper extends FieldMapper {
|
||||||
if (getTextSearchInfo().hasPositions() == false) {
|
if (getTextSearchInfo().hasPositions() == false) {
|
||||||
throw new IllegalArgumentException("Cannot create intervals over field [" + name() + "] with no positions indexed");
|
throw new IllegalArgumentException("Cannot create intervals over field [" + name() + "] with no positions indexed");
|
||||||
}
|
}
|
||||||
FuzzyQuery fq = new FuzzyQuery(new Term(name(), term), maxDistance, prefixLength, 128, transpositions);
|
FuzzyQuery fq = new FuzzyQuery(
|
||||||
return Intervals.multiterm(fq.getAutomata(), term);
|
new Term(name(), term),
|
||||||
|
maxDistance,
|
||||||
|
prefixLength,
|
||||||
|
IndexSearcher.getMaxClauseCount(),
|
||||||
|
transpositions
|
||||||
|
);
|
||||||
|
return Intervals.multiterm(fq.getAutomata(), IndexSearcher.getMaxClauseCount(), term);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -845,7 +855,29 @@ public final class TextFieldMapper extends FieldMapper {
|
||||||
if (getTextSearchInfo().hasPositions() == false) {
|
if (getTextSearchInfo().hasPositions() == false) {
|
||||||
throw new IllegalArgumentException("Cannot create intervals over field [" + name() + "] with no positions indexed");
|
throw new IllegalArgumentException("Cannot create intervals over field [" + name() + "] with no positions indexed");
|
||||||
}
|
}
|
||||||
return Intervals.wildcard(pattern);
|
return Intervals.wildcard(pattern, IndexSearcher.getMaxClauseCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntervalsSource regexpIntervals(BytesRef pattern, SearchExecutionContext context) {
|
||||||
|
if (getTextSearchInfo().hasPositions() == false) {
|
||||||
|
throw new IllegalArgumentException("Cannot create intervals over field [" + name() + "] with no positions indexed");
|
||||||
|
}
|
||||||
|
return Intervals.regexp(pattern, IndexSearcher.getMaxClauseCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntervalsSource rangeIntervals(
|
||||||
|
BytesRef lowerTerm,
|
||||||
|
BytesRef upperTerm,
|
||||||
|
boolean includeLower,
|
||||||
|
boolean includeUpper,
|
||||||
|
SearchExecutionContext context
|
||||||
|
) {
|
||||||
|
if (getTextSearchInfo().hasPositions() == false) {
|
||||||
|
throw new IllegalArgumentException("Cannot create intervals over field [" + name() + "] with no positions indexed");
|
||||||
|
}
|
||||||
|
return Intervals.range(lowerTerm, upperTerm, includeLower, includeUpper, IndexSearcher.getMaxClauseCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkForPositions() {
|
private void checkForPositions() {
|
||||||
|
|
|
@ -14,11 +14,13 @@ import org.apache.lucene.queries.intervals.IntervalIterator;
|
||||||
import org.apache.lucene.queries.intervals.Intervals;
|
import org.apache.lucene.queries.intervals.Intervals;
|
||||||
import org.apache.lucene.queries.intervals.IntervalsSource;
|
import org.apache.lucene.queries.intervals.IntervalsSource;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
|
import org.elasticsearch.TransportVersion;
|
||||||
import org.elasticsearch.TransportVersions;
|
import org.elasticsearch.TransportVersions;
|
||||||
import org.elasticsearch.common.ParsingException;
|
import org.elasticsearch.common.ParsingException;
|
||||||
import org.elasticsearch.common.io.stream.NamedWriteable;
|
import org.elasticsearch.common.io.stream.NamedWriteable;
|
||||||
import org.elasticsearch.common.io.stream.StreamInput;
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
|
import org.elasticsearch.common.io.stream.VersionedNamedWriteable;
|
||||||
import org.elasticsearch.common.io.stream.Writeable;
|
import org.elasticsearch.common.io.stream.Writeable;
|
||||||
import org.elasticsearch.common.unit.Fuzziness;
|
import org.elasticsearch.common.unit.Fuzziness;
|
||||||
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
import org.elasticsearch.index.analysis.NamedAnalyzer;
|
||||||
|
@ -77,10 +79,16 @@ public abstract class IntervalsSourceProvider implements NamedWriteable, ToXCont
|
||||||
return Wildcard.fromXContent(parser);
|
return Wildcard.fromXContent(parser);
|
||||||
case "fuzzy":
|
case "fuzzy":
|
||||||
return Fuzzy.fromXContent(parser);
|
return Fuzzy.fromXContent(parser);
|
||||||
|
case "regexp":
|
||||||
|
return Regexp.fromXContent(parser);
|
||||||
|
case "range":
|
||||||
|
return Range.fromXContent(parser);
|
||||||
}
|
}
|
||||||
throw new ParsingException(
|
throw new ParsingException(
|
||||||
parser.getTokenLocation(),
|
parser.getTokenLocation(),
|
||||||
"Unknown interval type [" + parser.currentName() + "], expecting one of [match, any_of, all_of, prefix, wildcard]"
|
"Unknown interval type ["
|
||||||
|
+ parser.currentName()
|
||||||
|
+ "], expecting one of [match, any_of, all_of, prefix, wildcard, regexp, range]"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -747,6 +755,129 @@ public abstract class IntervalsSourceProvider implements NamedWriteable, ToXCont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Regexp extends IntervalsSourceProvider implements VersionedNamedWriteable {
|
||||||
|
|
||||||
|
public static final String NAME = "regexp";
|
||||||
|
|
||||||
|
private final String pattern;
|
||||||
|
private final String analyzer;
|
||||||
|
private final String useField;
|
||||||
|
|
||||||
|
public Regexp(String pattern, String analyzer, String useField) {
|
||||||
|
this.pattern = pattern;
|
||||||
|
this.analyzer = analyzer;
|
||||||
|
this.useField = useField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Regexp(StreamInput in) throws IOException {
|
||||||
|
this.pattern = in.readString();
|
||||||
|
this.analyzer = in.readOptionalString();
|
||||||
|
this.useField = in.readOptionalString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntervalsSource getSource(SearchExecutionContext context, MappedFieldType fieldType) {
|
||||||
|
NamedAnalyzer analyzer = null;
|
||||||
|
if (this.analyzer != null) {
|
||||||
|
analyzer = context.getIndexAnalyzers().get(this.analyzer);
|
||||||
|
}
|
||||||
|
if (useField != null) {
|
||||||
|
fieldType = context.getFieldType(useField);
|
||||||
|
assert fieldType != null;
|
||||||
|
}
|
||||||
|
if (analyzer == null) {
|
||||||
|
analyzer = fieldType.getTextSearchInfo().searchAnalyzer();
|
||||||
|
}
|
||||||
|
BytesRef normalizedPattern = analyzer.normalize(fieldType.name(), pattern);
|
||||||
|
IntervalsSource source = fieldType.regexpIntervals(normalizedPattern, context);
|
||||||
|
if (useField != null) {
|
||||||
|
source = Intervals.fixField(useField, source);
|
||||||
|
}
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void extractFields(Set<String> fields) {
|
||||||
|
if (useField != null) {
|
||||||
|
fields.add(useField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Regexp regexp = (Regexp) o;
|
||||||
|
return Objects.equals(pattern, regexp.pattern)
|
||||||
|
&& Objects.equals(analyzer, regexp.analyzer)
|
||||||
|
&& Objects.equals(useField, regexp.useField);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(pattern, analyzer, useField);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getWriteableName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TransportVersion getMinimalSupportedVersion() {
|
||||||
|
return TransportVersions.REGEX_AND_RANGE_INTERVAL_QUERIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
|
out.writeString(pattern);
|
||||||
|
out.writeOptionalString(analyzer);
|
||||||
|
out.writeOptionalString(useField);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
|
builder.startObject(NAME);
|
||||||
|
builder.field("pattern", pattern);
|
||||||
|
if (analyzer != null) {
|
||||||
|
builder.field("analyzer", analyzer);
|
||||||
|
}
|
||||||
|
if (useField != null) {
|
||||||
|
builder.field("use_field", useField);
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final ConstructingObjectParser<Regexp, Void> PARSER = new ConstructingObjectParser<>(NAME, args -> {
|
||||||
|
String term = (String) args[0];
|
||||||
|
String analyzer = (String) args[1];
|
||||||
|
String useField = (String) args[2];
|
||||||
|
return new Regexp(term, analyzer, useField);
|
||||||
|
});
|
||||||
|
static {
|
||||||
|
PARSER.declareString(constructorArg(), new ParseField("pattern"));
|
||||||
|
PARSER.declareString(optionalConstructorArg(), new ParseField("analyzer"));
|
||||||
|
PARSER.declareString(optionalConstructorArg(), new ParseField("use_field"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Regexp fromXContent(XContentParser parser) throws IOException {
|
||||||
|
return PARSER.parse(parser, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
String getPattern() {
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getAnalyzer() {
|
||||||
|
return analyzer;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getUseField() {
|
||||||
|
return useField;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class Fuzzy extends IntervalsSourceProvider {
|
public static class Fuzzy extends IntervalsSourceProvider {
|
||||||
|
|
||||||
public static final String NAME = "fuzzy";
|
public static final String NAME = "fuzzy";
|
||||||
|
@ -908,6 +1039,190 @@ public abstract class IntervalsSourceProvider implements NamedWriteable, ToXCont
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Range extends IntervalsSourceProvider implements VersionedNamedWriteable {
|
||||||
|
|
||||||
|
public static final String NAME = "range";
|
||||||
|
|
||||||
|
private final String lowerTerm;
|
||||||
|
private final String upperTerm;
|
||||||
|
private final boolean includeLower;
|
||||||
|
private final boolean includeUpper;
|
||||||
|
private final String analyzer;
|
||||||
|
private final String useField;
|
||||||
|
|
||||||
|
public Range(String lowerTerm, String upperTerm, boolean includeLower, boolean includeUpper, String analyzer, String useField) {
|
||||||
|
this.lowerTerm = lowerTerm;
|
||||||
|
this.upperTerm = upperTerm;
|
||||||
|
this.includeLower = includeLower;
|
||||||
|
this.includeUpper = includeUpper;
|
||||||
|
this.analyzer = analyzer;
|
||||||
|
this.useField = useField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Range(StreamInput in) throws IOException {
|
||||||
|
this.lowerTerm = in.readString();
|
||||||
|
this.upperTerm = in.readString();
|
||||||
|
this.includeLower = in.readBoolean();
|
||||||
|
this.includeUpper = in.readBoolean();
|
||||||
|
this.analyzer = in.readOptionalString();
|
||||||
|
this.useField = in.readOptionalString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IntervalsSource getSource(SearchExecutionContext context, MappedFieldType fieldType) {
|
||||||
|
NamedAnalyzer analyzer = null;
|
||||||
|
if (this.analyzer != null) {
|
||||||
|
analyzer = context.getIndexAnalyzers().get(this.analyzer);
|
||||||
|
}
|
||||||
|
if (useField != null) {
|
||||||
|
fieldType = context.getFieldType(useField);
|
||||||
|
assert fieldType != null;
|
||||||
|
}
|
||||||
|
if (analyzer == null) {
|
||||||
|
analyzer = fieldType.getTextSearchInfo().searchAnalyzer();
|
||||||
|
}
|
||||||
|
BytesRef normalizedLowerTerm = analyzer.normalize(fieldType.name(), lowerTerm);
|
||||||
|
BytesRef normalizedUpperTerm = analyzer.normalize(fieldType.name(), upperTerm);
|
||||||
|
|
||||||
|
IntervalsSource source = fieldType.rangeIntervals(
|
||||||
|
normalizedLowerTerm,
|
||||||
|
normalizedUpperTerm,
|
||||||
|
includeLower,
|
||||||
|
includeUpper,
|
||||||
|
context
|
||||||
|
);
|
||||||
|
if (useField != null) {
|
||||||
|
source = Intervals.fixField(useField, source);
|
||||||
|
}
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void extractFields(Set<String> fields) {
|
||||||
|
if (useField != null) {
|
||||||
|
fields.add(useField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
Range range = (Range) o;
|
||||||
|
return includeLower == range.includeLower
|
||||||
|
&& includeUpper == range.includeUpper
|
||||||
|
&& Objects.equals(lowerTerm, range.lowerTerm)
|
||||||
|
&& Objects.equals(upperTerm, range.upperTerm)
|
||||||
|
&& Objects.equals(analyzer, range.analyzer)
|
||||||
|
&& Objects.equals(useField, range.useField);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(lowerTerm, upperTerm, includeLower, includeUpper, analyzer, useField);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getWriteableName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TransportVersion getMinimalSupportedVersion() {
|
||||||
|
return TransportVersions.REGEX_AND_RANGE_INTERVAL_QUERIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
|
out.writeString(lowerTerm);
|
||||||
|
out.writeString(upperTerm);
|
||||||
|
out.writeBoolean(includeLower);
|
||||||
|
out.writeBoolean(includeUpper);
|
||||||
|
out.writeOptionalString(analyzer);
|
||||||
|
out.writeOptionalString(useField);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
|
builder.startObject(NAME);
|
||||||
|
if (includeLower) {
|
||||||
|
builder.field("gte", lowerTerm);
|
||||||
|
} else {
|
||||||
|
builder.field("gt", lowerTerm);
|
||||||
|
}
|
||||||
|
if (includeUpper) {
|
||||||
|
builder.field("lte", upperTerm);
|
||||||
|
} else {
|
||||||
|
builder.field("lt", upperTerm);
|
||||||
|
}
|
||||||
|
if (analyzer != null) {
|
||||||
|
builder.field("analyzer", analyzer);
|
||||||
|
}
|
||||||
|
if (useField != null) {
|
||||||
|
builder.field("use_field", useField);
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final ConstructingObjectParser<Range, Void> PARSER = new ConstructingObjectParser<>(NAME, args -> {
|
||||||
|
String gte = (String) args[0];
|
||||||
|
String gt = (String) args[1];
|
||||||
|
String lte = (String) args[2];
|
||||||
|
String lt = (String) args[3];
|
||||||
|
if ((gte == null && gt == null) || (gte != null && gt != null)) {
|
||||||
|
throw new IllegalArgumentException("Either [gte] or [gt], one of them must be provided");
|
||||||
|
}
|
||||||
|
if ((lte == null && lt == null) || (lte != null && lt != null)) {
|
||||||
|
throw new IllegalArgumentException("Either [lte] or [lt], one of them must be provided");
|
||||||
|
}
|
||||||
|
boolean includeLower = gte != null ? true : false;
|
||||||
|
String lowerTerm = gte != null ? gte : gt;
|
||||||
|
boolean includeUpper = lte != null ? true : false;
|
||||||
|
String upperTerm = lte != null ? lte : lt;
|
||||||
|
String analyzer = (String) args[4];
|
||||||
|
String useField = (String) args[5];
|
||||||
|
return new Range(lowerTerm, upperTerm, includeLower, includeUpper, analyzer, useField);
|
||||||
|
});
|
||||||
|
|
||||||
|
static {
|
||||||
|
PARSER.declareString(optionalConstructorArg(), new ParseField("gte"));
|
||||||
|
PARSER.declareString(optionalConstructorArg(), new ParseField("gt"));
|
||||||
|
PARSER.declareString(optionalConstructorArg(), new ParseField("lte"));
|
||||||
|
PARSER.declareString(optionalConstructorArg(), new ParseField("lt"));
|
||||||
|
PARSER.declareString(optionalConstructorArg(), new ParseField("analyzer"));
|
||||||
|
PARSER.declareString(optionalConstructorArg(), new ParseField("use_field"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Range fromXContent(XContentParser parser) throws IOException {
|
||||||
|
return PARSER.parse(parser, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
String getLowerTerm() {
|
||||||
|
return lowerTerm;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getUpperTerm() {
|
||||||
|
return upperTerm;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean getIncludeLower() {
|
||||||
|
return includeLower;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean getIncludeUpper() {
|
||||||
|
return includeUpper;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getAnalyzer() {
|
||||||
|
return analyzer;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getUseField() {
|
||||||
|
return useField;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static class ScriptFilterSource extends FilteredIntervalsSource {
|
static class ScriptFilterSource extends FilteredIntervalsSource {
|
||||||
|
|
||||||
final IntervalFilterScript script;
|
final IntervalFilterScript script;
|
||||||
|
|
|
@ -57,6 +57,7 @@ public enum LuceneFilesExtensions {
|
||||||
NVM("nvm", "Norms Metadata", true, false),
|
NVM("nvm", "Norms Metadata", true, false),
|
||||||
PAY("pay", "Payloads", false, false),
|
PAY("pay", "Payloads", false, false),
|
||||||
POS("pos", "Positions", false, false),
|
POS("pos", "Positions", false, false),
|
||||||
|
PSM("psm", "Postings Metadata", true, false),
|
||||||
SI("si", "Segment Info", true, false),
|
SI("si", "Segment Info", true, false),
|
||||||
// Term dictionaries are typically performance-sensitive and hot in the page
|
// Term dictionaries are typically performance-sensitive and hot in the page
|
||||||
// cache, so we use mmap, which provides better performance.
|
// cache, so we use mmap, which provides better performance.
|
||||||
|
|
|
@ -1376,7 +1376,7 @@ public class RecoverySourceHandler {
|
||||||
// we already have the file contents on heap no need to open the file again
|
// we already have the file contents on heap no need to open the file again
|
||||||
currentInput = null;
|
currentInput = null;
|
||||||
} else {
|
} else {
|
||||||
currentInput = store.directory().openInput(md.name(), IOContext.READONCE);
|
currentInput = store.directory().openInput(md.name(), IOContext.READ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ public final class LegacyBM25Similarity extends Similarity {
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public LegacyBM25Similarity() {
|
public LegacyBM25Similarity() {
|
||||||
this.bm25Similarity = new BM25Similarity();
|
this(new BM25Similarity());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,7 +54,12 @@ public final class LegacyBM25Similarity extends Similarity {
|
||||||
* not within the range {@code [0..1]}
|
* not within the range {@code [0..1]}
|
||||||
*/
|
*/
|
||||||
public LegacyBM25Similarity(float k1, float b, boolean discountOverlaps) {
|
public LegacyBM25Similarity(float k1, float b, boolean discountOverlaps) {
|
||||||
this.bm25Similarity = new BM25Similarity(k1, b, discountOverlaps);
|
this(new BM25Similarity(k1, b, discountOverlaps));
|
||||||
|
}
|
||||||
|
|
||||||
|
private LegacyBM25Similarity(BM25Similarity bm25Similarity) {
|
||||||
|
super(bm25Similarity.getDiscountOverlaps());
|
||||||
|
this.bm25Similarity = bm25Similarity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -81,13 +86,6 @@ public final class LegacyBM25Similarity extends Similarity {
|
||||||
return bm25Similarity.getB();
|
return bm25Similarity.getB();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if overlap tokens are discounted from the document's length.
|
|
||||||
*/
|
|
||||||
public boolean getDiscountOverlaps() {
|
|
||||||
return bm25Similarity.getDiscountOverlaps();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return bm25Similarity.toString();
|
return bm25Similarity.toString();
|
||||||
|
|
|
@ -77,6 +77,19 @@ public final class CombinedBitSet extends BitSet implements Bits {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nextSetBit(int index, int upperBound) {
|
||||||
|
assert index >= 0 && index < length : "index=" + index + " numBits=" + length();
|
||||||
|
int next = first.nextSetBit(index, upperBound);
|
||||||
|
while (next != DocIdSetIterator.NO_MORE_DOCS && second.get(next) == false) {
|
||||||
|
if (next == length() - 1) {
|
||||||
|
return DocIdSetIterator.NO_MORE_DOCS;
|
||||||
|
}
|
||||||
|
next = first.nextSetBit(next + 1, upperBound);
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long ramBytesUsed() {
|
public long ramBytesUsed() {
|
||||||
return first.ramBytesUsed();
|
return first.ramBytesUsed();
|
||||||
|
|
|
@ -69,6 +69,12 @@ public final class MatchAllBitSet extends BitSet {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int nextSetBit(int index, int upperBound) {
|
||||||
|
assert index < upperBound;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long ramBytesUsed() {
|
public long ramBytesUsed() {
|
||||||
return RAM_BYTES_USED;
|
return RAM_BYTES_USED;
|
||||||
|
|
|
@ -85,6 +85,7 @@ import org.elasticsearch.core.IOUtils;
|
||||||
import org.elasticsearch.core.SuppressForbidden;
|
import org.elasticsearch.core.SuppressForbidden;
|
||||||
import org.elasticsearch.core.TimeValue;
|
import org.elasticsearch.core.TimeValue;
|
||||||
import org.elasticsearch.core.Tuple;
|
import org.elasticsearch.core.Tuple;
|
||||||
|
import org.elasticsearch.core.UpdateForV9;
|
||||||
import org.elasticsearch.discovery.DiscoveryModule;
|
import org.elasticsearch.discovery.DiscoveryModule;
|
||||||
import org.elasticsearch.env.Environment;
|
import org.elasticsearch.env.Environment;
|
||||||
import org.elasticsearch.env.NodeEnvironment;
|
import org.elasticsearch.env.NodeEnvironment;
|
||||||
|
@ -509,6 +510,7 @@ class NodeConstruction {
|
||||||
for (final ExecutorBuilder<?> builder : threadPool.builders()) {
|
for (final ExecutorBuilder<?> builder : threadPool.builders()) {
|
||||||
additionalSettings.addAll(builder.getRegisteredSettings());
|
additionalSettings.addAll(builder.getRegisteredSettings());
|
||||||
}
|
}
|
||||||
|
addBwcSearchWorkerSettings(additionalSettings);
|
||||||
SettingsExtension.load().forEach(e -> additionalSettings.addAll(e.getSettings()));
|
SettingsExtension.load().forEach(e -> additionalSettings.addAll(e.getSettings()));
|
||||||
|
|
||||||
// this is as early as we can validate settings at this point. we already pass them to ThreadPool
|
// this is as early as we can validate settings at this point. we already pass them to ThreadPool
|
||||||
|
@ -539,6 +541,17 @@ class NodeConstruction {
|
||||||
return settingsModule;
|
return settingsModule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UpdateForV9
|
||||||
|
private static void addBwcSearchWorkerSettings(List<Setting<?>> additionalSettings) {
|
||||||
|
// TODO remove the below settings, they are unused and only here to enable BwC for deployments that still use them
|
||||||
|
additionalSettings.add(
|
||||||
|
Setting.intSetting("thread_pool.search_worker.queue_size", 0, Setting.Property.NodeScope, Setting.Property.DeprecatedWarning)
|
||||||
|
);
|
||||||
|
additionalSettings.add(
|
||||||
|
Setting.intSetting("thread_pool.search_worker.size", 0, Setting.Property.NodeScope, Setting.Property.DeprecatedWarning)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private SearchModule createSearchModule(Settings settings, ThreadPool threadPool, TelemetryProvider telemetryProvider) {
|
private SearchModule createSearchModule(Settings settings, ThreadPool threadPool, TelemetryProvider telemetryProvider) {
|
||||||
IndexSearcher.setMaxClauseCount(SearchUtils.calculateMaxClauseValue(threadPool));
|
IndexSearcher.setMaxClauseCount(SearchUtils.calculateMaxClauseValue(threadPool));
|
||||||
return new SearchModule(settings, pluginsService.filterPlugins(SearchPlugin.class).toList(), telemetryProvider);
|
return new SearchModule(settings, pluginsService.filterPlugins(SearchPlugin.class).toList(), telemetryProvider);
|
||||||
|
|
|
@ -4030,7 +4030,7 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
|
||||||
final String file = fileInfo.physicalName();
|
final String file = fileInfo.physicalName();
|
||||||
try (
|
try (
|
||||||
Releasable ignored = context.withCommitRef();
|
Releasable ignored = context.withCommitRef();
|
||||||
IndexInput indexInput = store.openVerifyingInput(file, IOContext.READONCE, fileInfo.metadata())
|
IndexInput indexInput = store.openVerifyingInput(file, IOContext.READ, fileInfo.metadata())
|
||||||
) {
|
) {
|
||||||
for (int i = 0; i < fileInfo.numberOfParts(); i++) {
|
for (int i = 0; i < fileInfo.numberOfParts(); i++) {
|
||||||
final long partBytes = fileInfo.partBytes(i);
|
final long partBytes = fileInfo.partBytes(i);
|
||||||
|
|
|
@ -95,6 +95,11 @@ public class RestSearchAction extends BaseRestHandler {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> supportedCapabilities() {
|
||||||
|
return SearchCapabilities.CAPABILITIES;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
|
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the "Elastic License
|
||||||
|
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||||
|
* Public License v 1"; you may not use this file except in compliance with, at
|
||||||
|
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||||
|
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.rest.action.search;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link Set} of "capabilities" supported by the {@link RestSearchAction}.
|
||||||
|
*/
|
||||||
|
public final class SearchCapabilities {
|
||||||
|
|
||||||
|
private SearchCapabilities() {}
|
||||||
|
|
||||||
|
/** Support regex and range match rules in interval queries. */
|
||||||
|
private static final String RANGE_REGEX_INTERVAL_QUERY_CAPABILITY = "range_regexp_interval_queries";
|
||||||
|
|
||||||
|
public static final Set<String> CAPABILITIES = Set.of(RANGE_REGEX_INTERVAL_QUERY_CAPABILITY);
|
||||||
|
}
|
|
@ -180,7 +180,14 @@ final class DefaultSearchContext extends SearchContext {
|
||||||
this.indexShard = readerContext.indexShard();
|
this.indexShard = readerContext.indexShard();
|
||||||
|
|
||||||
Engine.Searcher engineSearcher = readerContext.acquireSearcher("search");
|
Engine.Searcher engineSearcher = readerContext.acquireSearcher("search");
|
||||||
if (executor == null) {
|
int maximumNumberOfSlices = determineMaximumNumberOfSlices(
|
||||||
|
executor,
|
||||||
|
request,
|
||||||
|
resultsType,
|
||||||
|
enableQueryPhaseParallelCollection,
|
||||||
|
field -> getFieldCardinality(field, readerContext.indexService(), engineSearcher.getDirectoryReader())
|
||||||
|
);
|
||||||
|
if (executor == null || maximumNumberOfSlices <= 1) {
|
||||||
this.searcher = new ContextIndexSearcher(
|
this.searcher = new ContextIndexSearcher(
|
||||||
engineSearcher.getIndexReader(),
|
engineSearcher.getIndexReader(),
|
||||||
engineSearcher.getSimilarity(),
|
engineSearcher.getSimilarity(),
|
||||||
|
@ -196,13 +203,7 @@ final class DefaultSearchContext extends SearchContext {
|
||||||
engineSearcher.getQueryCachingPolicy(),
|
engineSearcher.getQueryCachingPolicy(),
|
||||||
lowLevelCancellation,
|
lowLevelCancellation,
|
||||||
executor,
|
executor,
|
||||||
determineMaximumNumberOfSlices(
|
maximumNumberOfSlices,
|
||||||
executor,
|
|
||||||
request,
|
|
||||||
resultsType,
|
|
||||||
enableQueryPhaseParallelCollection,
|
|
||||||
field -> getFieldCardinality(field, readerContext.indexService(), engineSearcher.getDirectoryReader())
|
|
||||||
),
|
|
||||||
minimumDocsPerSlice
|
minimumDocsPerSlice
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -290,6 +291,7 @@ final class DefaultSearchContext extends SearchContext {
|
||||||
ToLongFunction<String> fieldCardinality
|
ToLongFunction<String> fieldCardinality
|
||||||
) {
|
) {
|
||||||
return executor instanceof ThreadPoolExecutor tpe
|
return executor instanceof ThreadPoolExecutor tpe
|
||||||
|
&& tpe.getQueue().isEmpty()
|
||||||
&& isParallelCollectionSupportedForResults(resultsType, request.source(), fieldCardinality, enableQueryPhaseParallelCollection)
|
&& isParallelCollectionSupportedForResults(resultsType, request.source(), fieldCardinality, enableQueryPhaseParallelCollection)
|
||||||
? tpe.getMaximumPoolSize()
|
? tpe.getMaximumPoolSize()
|
||||||
: 1;
|
: 1;
|
||||||
|
|
|
@ -1263,6 +1263,16 @@ public class SearchModule {
|
||||||
IntervalsSourceProvider.class,
|
IntervalsSourceProvider.class,
|
||||||
IntervalsSourceProvider.Fuzzy.NAME,
|
IntervalsSourceProvider.Fuzzy.NAME,
|
||||||
IntervalsSourceProvider.Fuzzy::new
|
IntervalsSourceProvider.Fuzzy::new
|
||||||
|
),
|
||||||
|
new NamedWriteableRegistry.Entry(
|
||||||
|
IntervalsSourceProvider.class,
|
||||||
|
IntervalsSourceProvider.Regexp.NAME,
|
||||||
|
IntervalsSourceProvider.Regexp::new
|
||||||
|
),
|
||||||
|
new NamedWriteableRegistry.Entry(
|
||||||
|
IntervalsSourceProvider.class,
|
||||||
|
IntervalsSourceProvider.Range.NAME,
|
||||||
|
IntervalsSourceProvider.Range::new
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,7 +142,6 @@ import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
@ -228,7 +227,8 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv
|
||||||
"search.worker_threads_enabled",
|
"search.worker_threads_enabled",
|
||||||
true,
|
true,
|
||||||
Property.NodeScope,
|
Property.NodeScope,
|
||||||
Property.Dynamic
|
Property.Dynamic,
|
||||||
|
Property.DeprecatedWarning
|
||||||
);
|
);
|
||||||
|
|
||||||
public static final Setting<Boolean> QUERY_PHASE_PARALLEL_COLLECTION_ENABLED = Setting.boolSetting(
|
public static final Setting<Boolean> QUERY_PHASE_PARALLEL_COLLECTION_ENABLED = Setting.boolSetting(
|
||||||
|
@ -279,7 +279,7 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv
|
||||||
|
|
||||||
private final FetchPhase fetchPhase;
|
private final FetchPhase fetchPhase;
|
||||||
private final RankFeatureShardPhase rankFeatureShardPhase;
|
private final RankFeatureShardPhase rankFeatureShardPhase;
|
||||||
private volatile boolean enableSearchWorkerThreads;
|
private volatile Executor searchExecutor;
|
||||||
private volatile boolean enableQueryPhaseParallelCollection;
|
private volatile boolean enableQueryPhaseParallelCollection;
|
||||||
|
|
||||||
private volatile long defaultKeepAlive;
|
private volatile long defaultKeepAlive;
|
||||||
|
@ -373,7 +373,10 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv
|
||||||
clusterService.getClusterSettings()
|
clusterService.getClusterSettings()
|
||||||
.addSettingsUpdateConsumer(ENABLE_REWRITE_AGGS_TO_FILTER_BY_FILTER, this::setEnableRewriteAggsToFilterByFilter);
|
.addSettingsUpdateConsumer(ENABLE_REWRITE_AGGS_TO_FILTER_BY_FILTER, this::setEnableRewriteAggsToFilterByFilter);
|
||||||
|
|
||||||
enableSearchWorkerThreads = SEARCH_WORKER_THREADS_ENABLED.get(settings);
|
if (SEARCH_WORKER_THREADS_ENABLED.get(settings)) {
|
||||||
|
searchExecutor = threadPool.executor(Names.SEARCH);
|
||||||
|
}
|
||||||
|
|
||||||
clusterService.getClusterSettings().addSettingsUpdateConsumer(SEARCH_WORKER_THREADS_ENABLED, this::setEnableSearchWorkerThreads);
|
clusterService.getClusterSettings().addSettingsUpdateConsumer(SEARCH_WORKER_THREADS_ENABLED, this::setEnableSearchWorkerThreads);
|
||||||
|
|
||||||
enableQueryPhaseParallelCollection = QUERY_PHASE_PARALLEL_COLLECTION_ENABLED.get(settings);
|
enableQueryPhaseParallelCollection = QUERY_PHASE_PARALLEL_COLLECTION_ENABLED.get(settings);
|
||||||
|
@ -382,7 +385,11 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setEnableSearchWorkerThreads(boolean enableSearchWorkerThreads) {
|
private void setEnableSearchWorkerThreads(boolean enableSearchWorkerThreads) {
|
||||||
this.enableSearchWorkerThreads = enableSearchWorkerThreads;
|
if (enableSearchWorkerThreads) {
|
||||||
|
searchExecutor = threadPool.executor(Names.SEARCH);
|
||||||
|
} else {
|
||||||
|
searchExecutor = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setEnableQueryPhaseParallelCollection(boolean enableQueryPhaseParallelCollection) {
|
private void setEnableQueryPhaseParallelCollection(boolean enableQueryPhaseParallelCollection) {
|
||||||
|
@ -1111,7 +1118,6 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv
|
||||||
reader.indexShard().shardId(),
|
reader.indexShard().shardId(),
|
||||||
request.getClusterAlias()
|
request.getClusterAlias()
|
||||||
);
|
);
|
||||||
ExecutorService executor = this.enableSearchWorkerThreads ? threadPool.executor(Names.SEARCH_WORKER) : null;
|
|
||||||
searchContext = new DefaultSearchContext(
|
searchContext = new DefaultSearchContext(
|
||||||
reader,
|
reader,
|
||||||
request,
|
request,
|
||||||
|
@ -1120,7 +1126,7 @@ public class SearchService extends AbstractLifecycleComponent implements IndexEv
|
||||||
timeout,
|
timeout,
|
||||||
fetchPhase,
|
fetchPhase,
|
||||||
lowLevelCancellation,
|
lowLevelCancellation,
|
||||||
executor,
|
searchExecutor,
|
||||||
resultsType,
|
resultsType,
|
||||||
enableQueryPhaseParallelCollection,
|
enableQueryPhaseParallelCollection,
|
||||||
minimumDocsPerSlice
|
minimumDocsPerSlice
|
||||||
|
|
|
@ -22,7 +22,6 @@ import org.apache.lucene.util.Bits;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.apache.lucene.util.BytesRefBuilder;
|
import org.apache.lucene.util.BytesRefBuilder;
|
||||||
import org.apache.lucene.util.PriorityQueue;
|
import org.apache.lucene.util.PriorityQueue;
|
||||||
import org.apache.lucene.util.ThreadInterruptedException;
|
|
||||||
import org.elasticsearch.cluster.metadata.DataStream;
|
import org.elasticsearch.cluster.metadata.DataStream;
|
||||||
import org.elasticsearch.common.lucene.search.function.MinScoreScorer;
|
import org.elasticsearch.common.lucene.search.function.MinScoreScorer;
|
||||||
import org.elasticsearch.index.mapper.DataStreamTimestampFieldMapper;
|
import org.elasticsearch.index.mapper.DataStreamTimestampFieldMapper;
|
||||||
|
@ -38,9 +37,6 @@ import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.FutureTask;
|
|
||||||
import java.util.concurrent.RunnableFuture;
|
|
||||||
import java.util.function.IntSupplier;
|
import java.util.function.IntSupplier;
|
||||||
|
|
||||||
import static org.elasticsearch.index.IndexSortConfig.TIME_SERIES_SORT;
|
import static org.elasticsearch.index.IndexSortConfig.TIME_SERIES_SORT;
|
||||||
|
@ -68,10 +64,7 @@ public class TimeSeriesIndexSearcher {
|
||||||
searcher.getSimilarity(),
|
searcher.getSimilarity(),
|
||||||
searcher.getQueryCache(),
|
searcher.getQueryCache(),
|
||||||
searcher.getQueryCachingPolicy(),
|
searcher.getQueryCachingPolicy(),
|
||||||
false,
|
false
|
||||||
searcher.getExecutor(),
|
|
||||||
1,
|
|
||||||
-1
|
|
||||||
);
|
);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// IOException from wrapping the index searcher which should never happen.
|
// IOException from wrapping the index searcher which should never happen.
|
||||||
|
@ -94,28 +87,8 @@ public class TimeSeriesIndexSearcher {
|
||||||
public void search(Query query, BucketCollector bucketCollector) throws IOException {
|
public void search(Query query, BucketCollector bucketCollector) throws IOException {
|
||||||
query = searcher.rewrite(query);
|
query = searcher.rewrite(query);
|
||||||
Weight weight = searcher.createWeight(query, bucketCollector.scoreMode(), 1);
|
Weight weight = searcher.createWeight(query, bucketCollector.scoreMode(), 1);
|
||||||
if (searcher.getExecutor() == null) {
|
search(bucketCollector, weight);
|
||||||
search(bucketCollector, weight);
|
bucketCollector.postCollection();
|
||||||
bucketCollector.postCollection();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// offload to the search worker thread pool whenever possible. It will be null only when search.worker_threads_enabled is false
|
|
||||||
RunnableFuture<Void> task = new FutureTask<>(() -> {
|
|
||||||
search(bucketCollector, weight);
|
|
||||||
bucketCollector.postCollection();
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
searcher.getExecutor().execute(task);
|
|
||||||
try {
|
|
||||||
task.get();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new ThreadInterruptedException(e);
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
if (e.getCause() instanceof RuntimeException runtimeException) {
|
|
||||||
throw runtimeException;
|
|
||||||
}
|
|
||||||
throw new RuntimeException(e.getCause());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void search(BucketCollector bucketCollector, Weight weight) throws IOException {
|
private void search(BucketCollector bucketCollector, Weight weight) throws IOException {
|
||||||
|
|
|
@ -322,12 +322,9 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Similar to the lucene implementation, with the following changes made:
|
* Same implementation as the default one in Lucene, with an additional call to postCollection in cased there are no segments.
|
||||||
* 1) postCollection is performed after each segment is collected. This is needed for aggregations, performed by search worker threads
|
* The rest is a plain copy from Lucene.
|
||||||
* so it can be parallelized. Also, it needs to happen in the same thread where doc_values are read, as it consumes them and Lucene
|
*/
|
||||||
* does not allow consuming them from a different thread.
|
|
||||||
* 2) handles the ES TimeExceededException
|
|
||||||
* */
|
|
||||||
private <C extends Collector, T> T search(Weight weight, CollectorManager<C, T> collectorManager, C firstCollector) throws IOException {
|
private <C extends Collector, T> T search(Weight weight, CollectorManager<C, T> collectorManager, C firstCollector) throws IOException {
|
||||||
LeafSlice[] leafSlices = getSlices();
|
LeafSlice[] leafSlices = getSlices();
|
||||||
if (leafSlices.length == 0) {
|
if (leafSlices.length == 0) {
|
||||||
|
@ -359,14 +356,18 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to the lucene implementation, with the following changes made:
|
||||||
|
* 1) postCollection is performed after each segment is collected. This is needed for aggregations, performed by search threads
|
||||||
|
* so it can be parallelized. Also, it needs to happen in the same thread where doc_values are read, as it consumes them and Lucene
|
||||||
|
* does not allow consuming them from a different thread.
|
||||||
|
* 2) handles the ES TimeExceededException
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void search(List<LeafReaderContext> leaves, Weight weight, Collector collector) throws IOException {
|
public void search(List<LeafReaderContext> leaves, Weight weight, Collector collector) throws IOException {
|
||||||
collector.setWeight(weight);
|
|
||||||
boolean success = false;
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
for (LeafReaderContext ctx : leaves) { // search each subreader
|
super.search(leaves, weight, collector);
|
||||||
searchLeaf(ctx, weight, collector);
|
|
||||||
}
|
|
||||||
success = true;
|
success = true;
|
||||||
} catch (@SuppressWarnings("unused") TimeExceededException e) {
|
} catch (@SuppressWarnings("unused") TimeExceededException e) {
|
||||||
timeExceeded = true;
|
timeExceeded = true;
|
||||||
|
@ -410,13 +411,8 @@ public class ContextIndexSearcher extends IndexSearcher implements Releasable {
|
||||||
// This exception should never be re-thrown, but we fill in the stacktrace to be able to trace where it does not get properly caught
|
// This exception should never be re-thrown, but we fill in the stacktrace to be able to trace where it does not get properly caught
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Lower-level search API.
|
protected void searchLeaf(LeafReaderContext ctx, Weight weight, Collector collector) throws IOException {
|
||||||
*
|
|
||||||
* {@link LeafCollector#collect(int)} is called for every matching document in
|
|
||||||
* the provided <code>ctx</code>.
|
|
||||||
*/
|
|
||||||
private void searchLeaf(LeafReaderContext ctx, Weight weight, Collector collector) throws IOException {
|
|
||||||
cancellable.checkCancelled();
|
cancellable.checkCancelled();
|
||||||
final LeafCollector leafCollector;
|
final LeafCollector leafCollector;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -72,16 +72,6 @@ public class DefaultBuiltInExecutorBuilders implements BuiltInExecutorBuilders {
|
||||||
new EsExecutors.TaskTrackingConfig(true, searchAutoscalingEWMA)
|
new EsExecutors.TaskTrackingConfig(true, searchAutoscalingEWMA)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
result.put(
|
|
||||||
ThreadPool.Names.SEARCH_WORKER,
|
|
||||||
new FixedExecutorBuilder(
|
|
||||||
settings,
|
|
||||||
ThreadPool.Names.SEARCH_WORKER,
|
|
||||||
searchOrGetThreadPoolSize,
|
|
||||||
-1,
|
|
||||||
EsExecutors.TaskTrackingConfig.DEFAULT
|
|
||||||
)
|
|
||||||
);
|
|
||||||
result.put(
|
result.put(
|
||||||
ThreadPool.Names.SEARCH_COORDINATION,
|
ThreadPool.Names.SEARCH_COORDINATION,
|
||||||
new FixedExecutorBuilder(
|
new FixedExecutorBuilder(
|
||||||
|
|
|
@ -88,7 +88,6 @@ public class ThreadPool implements ReportingService<ThreadPoolInfo>, Scheduler {
|
||||||
public static final String ANALYZE = "analyze";
|
public static final String ANALYZE = "analyze";
|
||||||
public static final String WRITE = "write";
|
public static final String WRITE = "write";
|
||||||
public static final String SEARCH = "search";
|
public static final String SEARCH = "search";
|
||||||
public static final String SEARCH_WORKER = "search_worker";
|
|
||||||
public static final String SEARCH_COORDINATION = "search_coordination";
|
public static final String SEARCH_COORDINATION = "search_coordination";
|
||||||
public static final String AUTO_COMPLETE = "auto_complete";
|
public static final String AUTO_COMPLETE = "auto_complete";
|
||||||
public static final String SEARCH_THROTTLED = "search_throttled";
|
public static final String SEARCH_THROTTLED = "search_throttled";
|
||||||
|
@ -158,7 +157,6 @@ public class ThreadPool implements ReportingService<ThreadPoolInfo>, Scheduler {
|
||||||
entry(Names.ANALYZE, ThreadPoolType.FIXED),
|
entry(Names.ANALYZE, ThreadPoolType.FIXED),
|
||||||
entry(Names.WRITE, ThreadPoolType.FIXED),
|
entry(Names.WRITE, ThreadPoolType.FIXED),
|
||||||
entry(Names.SEARCH, ThreadPoolType.FIXED),
|
entry(Names.SEARCH, ThreadPoolType.FIXED),
|
||||||
entry(Names.SEARCH_WORKER, ThreadPoolType.FIXED),
|
|
||||||
entry(Names.SEARCH_COORDINATION, ThreadPoolType.FIXED),
|
entry(Names.SEARCH_COORDINATION, ThreadPoolType.FIXED),
|
||||||
entry(Names.AUTO_COMPLETE, ThreadPoolType.FIXED),
|
entry(Names.AUTO_COMPLETE, ThreadPoolType.FIXED),
|
||||||
entry(Names.MANAGEMENT, ThreadPoolType.SCALING),
|
entry(Names.MANAGEMENT, ThreadPoolType.SCALING),
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
org.elasticsearch.index.codec.Elasticsearch814Codec
|
org.elasticsearch.index.codec.Elasticsearch814Codec
|
||||||
|
org.elasticsearch.index.codec.Elasticsearch816Codec
|
||||||
|
|
|
@ -13,7 +13,7 @@ import org.apache.lucene.codecs.DocValuesFormat;
|
||||||
import org.apache.lucene.codecs.KnnVectorsFormat;
|
import org.apache.lucene.codecs.KnnVectorsFormat;
|
||||||
import org.apache.lucene.codecs.PostingsFormat;
|
import org.apache.lucene.codecs.PostingsFormat;
|
||||||
import org.apache.lucene.codecs.lucene90.Lucene90DocValuesFormat;
|
import org.apache.lucene.codecs.lucene90.Lucene90DocValuesFormat;
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99Codec;
|
import org.apache.lucene.codecs.lucene912.Lucene912Codec;
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99HnswVectorsFormat;
|
import org.apache.lucene.codecs.lucene99.Lucene99HnswVectorsFormat;
|
||||||
import org.apache.lucene.codecs.perfield.PerFieldDocValuesFormat;
|
import org.apache.lucene.codecs.perfield.PerFieldDocValuesFormat;
|
||||||
import org.apache.lucene.codecs.perfield.PerFieldKnnVectorsFormat;
|
import org.apache.lucene.codecs.perfield.PerFieldKnnVectorsFormat;
|
||||||
|
@ -54,7 +54,7 @@ import org.apache.lucene.search.QueryVisitor;
|
||||||
import org.apache.lucene.search.ScoreMode;
|
import org.apache.lucene.search.ScoreMode;
|
||||||
import org.apache.lucene.search.Scorer;
|
import org.apache.lucene.search.Scorer;
|
||||||
import org.apache.lucene.search.Weight;
|
import org.apache.lucene.search.Weight;
|
||||||
import org.apache.lucene.search.suggest.document.Completion99PostingsFormat;
|
import org.apache.lucene.search.suggest.document.Completion912PostingsFormat;
|
||||||
import org.apache.lucene.search.suggest.document.CompletionPostingsFormat;
|
import org.apache.lucene.search.suggest.document.CompletionPostingsFormat;
|
||||||
import org.apache.lucene.search.suggest.document.SuggestField;
|
import org.apache.lucene.search.suggest.document.SuggestField;
|
||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
|
@ -327,11 +327,11 @@ public class IndexDiskUsageAnalyzerTests extends ESTestCase {
|
||||||
public void testCompletionField() throws Exception {
|
public void testCompletionField() throws Exception {
|
||||||
IndexWriterConfig config = new IndexWriterConfig().setCommitOnClose(true)
|
IndexWriterConfig config = new IndexWriterConfig().setCommitOnClose(true)
|
||||||
.setUseCompoundFile(false)
|
.setUseCompoundFile(false)
|
||||||
.setCodec(new Lucene99Codec(Lucene99Codec.Mode.BEST_SPEED) {
|
.setCodec(new Lucene912Codec(Lucene912Codec.Mode.BEST_SPEED) {
|
||||||
@Override
|
@Override
|
||||||
public PostingsFormat getPostingsFormatForField(String field) {
|
public PostingsFormat getPostingsFormatForField(String field) {
|
||||||
if (field.startsWith("suggest_")) {
|
if (field.startsWith("suggest_")) {
|
||||||
return new Completion99PostingsFormat(randomFrom(CompletionPostingsFormat.FSTLoadMode.values()));
|
return new Completion912PostingsFormat(randomFrom(CompletionPostingsFormat.FSTLoadMode.values()));
|
||||||
} else {
|
} else {
|
||||||
return super.postingsFormat();
|
return super.postingsFormat();
|
||||||
}
|
}
|
||||||
|
@ -414,25 +414,25 @@ public class IndexDiskUsageAnalyzerTests extends ESTestCase {
|
||||||
enum CodecMode {
|
enum CodecMode {
|
||||||
BEST_SPEED {
|
BEST_SPEED {
|
||||||
@Override
|
@Override
|
||||||
Lucene99Codec.Mode mode() {
|
Lucene912Codec.Mode mode() {
|
||||||
return Lucene99Codec.Mode.BEST_SPEED;
|
return Lucene912Codec.Mode.BEST_SPEED;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
BEST_COMPRESSION {
|
BEST_COMPRESSION {
|
||||||
@Override
|
@Override
|
||||||
Lucene99Codec.Mode mode() {
|
Lucene912Codec.Mode mode() {
|
||||||
return Lucene99Codec.Mode.BEST_COMPRESSION;
|
return Lucene912Codec.Mode.BEST_COMPRESSION;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
abstract Lucene99Codec.Mode mode();
|
abstract Lucene912Codec.Mode mode();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void indexRandomly(Directory directory, CodecMode codecMode, int numDocs, Consumer<Document> addFields) throws IOException {
|
static void indexRandomly(Directory directory, CodecMode codecMode, int numDocs, Consumer<Document> addFields) throws IOException {
|
||||||
IndexWriterConfig config = new IndexWriterConfig().setCommitOnClose(true)
|
IndexWriterConfig config = new IndexWriterConfig().setCommitOnClose(true)
|
||||||
.setUseCompoundFile(randomBoolean())
|
.setUseCompoundFile(randomBoolean())
|
||||||
.setCodec(new Lucene99Codec(codecMode.mode()));
|
.setCodec(new Lucene912Codec(codecMode.mode()));
|
||||||
try (IndexWriter writer = new IndexWriter(directory, config)) {
|
try (IndexWriter writer = new IndexWriter(directory, config)) {
|
||||||
for (int i = 0; i < numDocs; i++) {
|
for (int i = 0; i < numDocs; i++) {
|
||||||
final Document doc = new Document();
|
final Document doc = new Document();
|
||||||
|
@ -640,7 +640,7 @@ public class IndexDiskUsageAnalyzerTests extends ESTestCase {
|
||||||
try (DirectoryReader reader = DirectoryReader.open(source)) {
|
try (DirectoryReader reader = DirectoryReader.open(source)) {
|
||||||
IndexWriterConfig config = new IndexWriterConfig().setSoftDeletesField(Lucene.SOFT_DELETES_FIELD)
|
IndexWriterConfig config = new IndexWriterConfig().setSoftDeletesField(Lucene.SOFT_DELETES_FIELD)
|
||||||
.setUseCompoundFile(randomBoolean())
|
.setUseCompoundFile(randomBoolean())
|
||||||
.setCodec(new Lucene99Codec(mode.mode()) {
|
.setCodec(new Lucene912Codec(mode.mode()) {
|
||||||
@Override
|
@Override
|
||||||
public PostingsFormat getPostingsFormatForField(String field) {
|
public PostingsFormat getPostingsFormatForField(String field) {
|
||||||
return new ES812PostingsFormat();
|
return new ES812PostingsFormat();
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class CodecTests extends ESTestCase {
|
||||||
assumeTrue("Only when zstd_stored_fields feature flag is enabled", CodecService.ZSTD_STORED_FIELDS_FEATURE_FLAG.isEnabled());
|
assumeTrue("Only when zstd_stored_fields feature flag is enabled", CodecService.ZSTD_STORED_FIELDS_FEATURE_FLAG.isEnabled());
|
||||||
CodecService codecService = createCodecService();
|
CodecService codecService = createCodecService();
|
||||||
assertThat(codecService.codec("default"), instanceOf(PerFieldMapperCodec.class));
|
assertThat(codecService.codec("default"), instanceOf(PerFieldMapperCodec.class));
|
||||||
assertThat(codecService.codec("default"), instanceOf(Elasticsearch814Codec.class));
|
assertThat(codecService.codec("default"), instanceOf(Elasticsearch816Codec.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDefault() throws Exception {
|
public void testDefault() throws Exception {
|
||||||
|
|
|
@ -11,7 +11,7 @@ package org.elasticsearch.index.codec.vectors;
|
||||||
|
|
||||||
import org.apache.lucene.codecs.Codec;
|
import org.apache.lucene.codecs.Codec;
|
||||||
import org.apache.lucene.codecs.KnnVectorsFormat;
|
import org.apache.lucene.codecs.KnnVectorsFormat;
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99Codec;
|
import org.apache.lucene.codecs.lucene912.Lucene912Codec;
|
||||||
import org.apache.lucene.tests.index.BaseKnnVectorsFormatTestCase;
|
import org.apache.lucene.tests.index.BaseKnnVectorsFormatTestCase;
|
||||||
import org.elasticsearch.common.logging.LogConfigurator;
|
import org.elasticsearch.common.logging.LogConfigurator;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public class ES813FlatVectorFormatTests extends BaseKnnVectorsFormatTestCase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Codec getCodec() {
|
protected Codec getCodec() {
|
||||||
return new Lucene99Codec() {
|
return new Lucene912Codec() {
|
||||||
@Override
|
@Override
|
||||||
public KnnVectorsFormat getKnnVectorsFormatForField(String field) {
|
public KnnVectorsFormat getKnnVectorsFormatForField(String field) {
|
||||||
return new ES813FlatVectorFormat();
|
return new ES813FlatVectorFormat();
|
||||||
|
|
|
@ -11,7 +11,7 @@ package org.elasticsearch.index.codec.vectors;
|
||||||
|
|
||||||
import org.apache.lucene.codecs.Codec;
|
import org.apache.lucene.codecs.Codec;
|
||||||
import org.apache.lucene.codecs.KnnVectorsFormat;
|
import org.apache.lucene.codecs.KnnVectorsFormat;
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99Codec;
|
import org.apache.lucene.codecs.lucene912.Lucene912Codec;
|
||||||
import org.apache.lucene.tests.index.BaseKnnVectorsFormatTestCase;
|
import org.apache.lucene.tests.index.BaseKnnVectorsFormatTestCase;
|
||||||
import org.elasticsearch.common.logging.LogConfigurator;
|
import org.elasticsearch.common.logging.LogConfigurator;
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ public class ES813Int8FlatVectorFormatTests extends BaseKnnVectorsFormatTestCase
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Codec getCodec() {
|
protected Codec getCodec() {
|
||||||
return new Lucene99Codec() {
|
return new Lucene912Codec() {
|
||||||
@Override
|
@Override
|
||||||
public KnnVectorsFormat getKnnVectorsFormatForField(String field) {
|
public KnnVectorsFormat getKnnVectorsFormatForField(String field) {
|
||||||
return new ES813Int8FlatVectorFormat();
|
return new ES813Int8FlatVectorFormat();
|
||||||
|
|
|
@ -11,7 +11,7 @@ package org.elasticsearch.index.codec.vectors;
|
||||||
|
|
||||||
import org.apache.lucene.codecs.Codec;
|
import org.apache.lucene.codecs.Codec;
|
||||||
import org.apache.lucene.codecs.KnnVectorsFormat;
|
import org.apache.lucene.codecs.KnnVectorsFormat;
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99Codec;
|
import org.apache.lucene.codecs.lucene912.Lucene912Codec;
|
||||||
import org.apache.lucene.document.Document;
|
import org.apache.lucene.document.Document;
|
||||||
import org.apache.lucene.document.Field;
|
import org.apache.lucene.document.Field;
|
||||||
import org.apache.lucene.document.KnnFloatVectorField;
|
import org.apache.lucene.document.KnnFloatVectorField;
|
||||||
|
@ -41,7 +41,7 @@ public class ES814HnswScalarQuantizedVectorsFormatTests extends BaseKnnVectorsFo
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Codec getCodec() {
|
protected Codec getCodec() {
|
||||||
return new Lucene99Codec() {
|
return new Lucene912Codec() {
|
||||||
@Override
|
@Override
|
||||||
public KnnVectorsFormat getKnnVectorsFormatForField(String field) {
|
public KnnVectorsFormat getKnnVectorsFormatForField(String field) {
|
||||||
return new ES814HnswScalarQuantizedVectorsFormat();
|
return new ES814HnswScalarQuantizedVectorsFormat();
|
||||||
|
|
|
@ -11,7 +11,7 @@ package org.elasticsearch.index.codec.vectors;
|
||||||
|
|
||||||
import org.apache.lucene.codecs.Codec;
|
import org.apache.lucene.codecs.Codec;
|
||||||
import org.apache.lucene.codecs.KnnVectorsFormat;
|
import org.apache.lucene.codecs.KnnVectorsFormat;
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99Codec;
|
import org.apache.lucene.codecs.lucene912.Lucene912Codec;
|
||||||
import org.apache.lucene.index.VectorSimilarityFunction;
|
import org.apache.lucene.index.VectorSimilarityFunction;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ public class ES815BitFlatVectorFormatTests extends BaseKnnBitVectorsFormatTestCa
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Codec getCodec() {
|
protected Codec getCodec() {
|
||||||
return new Lucene99Codec() {
|
return new Lucene912Codec() {
|
||||||
@Override
|
@Override
|
||||||
public KnnVectorsFormat getKnnVectorsFormatForField(String field) {
|
public KnnVectorsFormat getKnnVectorsFormatForField(String field) {
|
||||||
return new ES815BitFlatVectorFormat();
|
return new ES815BitFlatVectorFormat();
|
||||||
|
|
|
@ -11,7 +11,7 @@ package org.elasticsearch.index.codec.vectors;
|
||||||
|
|
||||||
import org.apache.lucene.codecs.Codec;
|
import org.apache.lucene.codecs.Codec;
|
||||||
import org.apache.lucene.codecs.KnnVectorsFormat;
|
import org.apache.lucene.codecs.KnnVectorsFormat;
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99Codec;
|
import org.apache.lucene.codecs.lucene912.Lucene912Codec;
|
||||||
import org.apache.lucene.index.VectorSimilarityFunction;
|
import org.apache.lucene.index.VectorSimilarityFunction;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ public class ES815HnswBitVectorsFormatTests extends BaseKnnBitVectorsFormatTestC
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Codec getCodec() {
|
protected Codec getCodec() {
|
||||||
return new Lucene99Codec() {
|
return new Lucene912Codec() {
|
||||||
@Override
|
@Override
|
||||||
public KnnVectorsFormat getKnnVectorsFormatForField(String field) {
|
public KnnVectorsFormat getKnnVectorsFormatForField(String field) {
|
||||||
return new ES815HnswBitVectorsFormat();
|
return new ES815HnswBitVectorsFormat();
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
package org.elasticsearch.index.codec.zstd;
|
package org.elasticsearch.index.codec.zstd;
|
||||||
|
|
||||||
import org.apache.lucene.codecs.Codec;
|
import org.apache.lucene.codecs.Codec;
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99Codec;
|
import org.apache.lucene.codecs.lucene912.Lucene912Codec;
|
||||||
import org.apache.lucene.document.Document;
|
import org.apache.lucene.document.Document;
|
||||||
import org.apache.lucene.document.StoredField;
|
import org.apache.lucene.document.StoredField;
|
||||||
import org.apache.lucene.index.DirectoryReader;
|
import org.apache.lucene.index.DirectoryReader;
|
||||||
|
@ -35,13 +35,13 @@ public class StoredFieldCodecDuelTests extends ESTestCase {
|
||||||
private static final String DOUBLE_FIELD = "double_field_5";
|
private static final String DOUBLE_FIELD = "double_field_5";
|
||||||
|
|
||||||
public void testDuelBestSpeed() throws IOException {
|
public void testDuelBestSpeed() throws IOException {
|
||||||
var baseline = new LegacyPerFieldMapperCodec(Lucene99Codec.Mode.BEST_SPEED, null, BigArrays.NON_RECYCLING_INSTANCE);
|
var baseline = new LegacyPerFieldMapperCodec(Lucene912Codec.Mode.BEST_SPEED, null, BigArrays.NON_RECYCLING_INSTANCE);
|
||||||
var contender = new PerFieldMapperCodec(Zstd814StoredFieldsFormat.Mode.BEST_SPEED, null, BigArrays.NON_RECYCLING_INSTANCE);
|
var contender = new PerFieldMapperCodec(Zstd814StoredFieldsFormat.Mode.BEST_SPEED, null, BigArrays.NON_RECYCLING_INSTANCE);
|
||||||
doTestDuel(baseline, contender);
|
doTestDuel(baseline, contender);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDuelBestCompression() throws IOException {
|
public void testDuelBestCompression() throws IOException {
|
||||||
var baseline = new LegacyPerFieldMapperCodec(Lucene99Codec.Mode.BEST_COMPRESSION, null, BigArrays.NON_RECYCLING_INSTANCE);
|
var baseline = new LegacyPerFieldMapperCodec(Lucene912Codec.Mode.BEST_COMPRESSION, null, BigArrays.NON_RECYCLING_INSTANCE);
|
||||||
var contender = new PerFieldMapperCodec(Zstd814StoredFieldsFormat.Mode.BEST_COMPRESSION, null, BigArrays.NON_RECYCLING_INSTANCE);
|
var contender = new PerFieldMapperCodec(Zstd814StoredFieldsFormat.Mode.BEST_COMPRESSION, null, BigArrays.NON_RECYCLING_INSTANCE);
|
||||||
doTestDuel(baseline, contender);
|
doTestDuel(baseline, contender);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,11 @@ package org.elasticsearch.index.codec.zstd;
|
||||||
|
|
||||||
import org.apache.lucene.codecs.Codec;
|
import org.apache.lucene.codecs.Codec;
|
||||||
import org.apache.lucene.tests.index.BaseStoredFieldsFormatTestCase;
|
import org.apache.lucene.tests.index.BaseStoredFieldsFormatTestCase;
|
||||||
import org.elasticsearch.index.codec.Elasticsearch814Codec;
|
import org.elasticsearch.index.codec.Elasticsearch816Codec;
|
||||||
|
|
||||||
public class Zstd814BestCompressionStoredFieldsFormatTests extends BaseStoredFieldsFormatTestCase {
|
public class Zstd814BestCompressionStoredFieldsFormatTests extends BaseStoredFieldsFormatTestCase {
|
||||||
|
|
||||||
private final Codec codec = new Elasticsearch814Codec(Zstd814StoredFieldsFormat.Mode.BEST_COMPRESSION);
|
private final Codec codec = new Elasticsearch816Codec(Zstd814StoredFieldsFormat.Mode.BEST_COMPRESSION);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Codec getCodec() {
|
protected Codec getCodec() {
|
||||||
|
|
|
@ -11,11 +11,11 @@ package org.elasticsearch.index.codec.zstd;
|
||||||
|
|
||||||
import org.apache.lucene.codecs.Codec;
|
import org.apache.lucene.codecs.Codec;
|
||||||
import org.apache.lucene.tests.index.BaseStoredFieldsFormatTestCase;
|
import org.apache.lucene.tests.index.BaseStoredFieldsFormatTestCase;
|
||||||
import org.elasticsearch.index.codec.Elasticsearch814Codec;
|
import org.elasticsearch.index.codec.Elasticsearch816Codec;
|
||||||
|
|
||||||
public class Zstd814BestSpeedStoredFieldsFormatTests extends BaseStoredFieldsFormatTestCase {
|
public class Zstd814BestSpeedStoredFieldsFormatTests extends BaseStoredFieldsFormatTestCase {
|
||||||
|
|
||||||
private final Codec codec = new Elasticsearch814Codec(Zstd814StoredFieldsFormat.Mode.BEST_SPEED);
|
private final Codec codec = new Elasticsearch816Codec(Zstd814StoredFieldsFormat.Mode.BEST_SPEED);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Codec getCodec() {
|
protected Codec getCodec() {
|
||||||
|
|
|
@ -9,12 +9,12 @@
|
||||||
package org.elasticsearch.index.engine;
|
package org.elasticsearch.index.engine;
|
||||||
|
|
||||||
import org.apache.lucene.codecs.PostingsFormat;
|
import org.apache.lucene.codecs.PostingsFormat;
|
||||||
import org.apache.lucene.codecs.lucene99.Lucene99Codec;
|
import org.apache.lucene.codecs.lucene912.Lucene912Codec;
|
||||||
import org.apache.lucene.document.Document;
|
import org.apache.lucene.document.Document;
|
||||||
import org.apache.lucene.index.DirectoryReader;
|
import org.apache.lucene.index.DirectoryReader;
|
||||||
import org.apache.lucene.index.IndexWriter;
|
import org.apache.lucene.index.IndexWriter;
|
||||||
import org.apache.lucene.index.IndexWriterConfig;
|
import org.apache.lucene.index.IndexWriterConfig;
|
||||||
import org.apache.lucene.search.suggest.document.Completion99PostingsFormat;
|
import org.apache.lucene.search.suggest.document.Completion912PostingsFormat;
|
||||||
import org.apache.lucene.search.suggest.document.SuggestField;
|
import org.apache.lucene.search.suggest.document.SuggestField;
|
||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
|
@ -44,8 +44,8 @@ public class CompletionStatsCacheTests extends ESTestCase {
|
||||||
|
|
||||||
public void testCompletionStatsCache() throws IOException, InterruptedException {
|
public void testCompletionStatsCache() throws IOException, InterruptedException {
|
||||||
final IndexWriterConfig indexWriterConfig = newIndexWriterConfig();
|
final IndexWriterConfig indexWriterConfig = newIndexWriterConfig();
|
||||||
final PostingsFormat postingsFormat = new Completion99PostingsFormat();
|
final PostingsFormat postingsFormat = new Completion912PostingsFormat();
|
||||||
indexWriterConfig.setCodec(new Lucene99Codec() {
|
indexWriterConfig.setCodec(new Lucene912Codec() {
|
||||||
@Override
|
@Override
|
||||||
public PostingsFormat getPostingsFormatForField(String field) {
|
public PostingsFormat getPostingsFormatForField(String field) {
|
||||||
return postingsFormat; // all fields are suggest fields
|
return postingsFormat; // all fields are suggest fields
|
||||||
|
|
|
@ -16,7 +16,7 @@ import org.apache.lucene.index.DocValuesType;
|
||||||
import org.apache.lucene.index.IndexOptions;
|
import org.apache.lucene.index.IndexOptions;
|
||||||
import org.apache.lucene.index.IndexableField;
|
import org.apache.lucene.index.IndexableField;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.search.suggest.document.Completion99PostingsFormat;
|
import org.apache.lucene.search.suggest.document.Completion912PostingsFormat;
|
||||||
import org.apache.lucene.search.suggest.document.CompletionAnalyzer;
|
import org.apache.lucene.search.suggest.document.CompletionAnalyzer;
|
||||||
import org.apache.lucene.search.suggest.document.ContextSuggestField;
|
import org.apache.lucene.search.suggest.document.ContextSuggestField;
|
||||||
import org.apache.lucene.search.suggest.document.FuzzyCompletionQuery;
|
import org.apache.lucene.search.suggest.document.FuzzyCompletionQuery;
|
||||||
|
@ -151,7 +151,7 @@ public class CompletionFieldMapperTests extends MapperTestCase {
|
||||||
Codec codec = codecService.codec("default");
|
Codec codec = codecService.codec("default");
|
||||||
if (CodecService.ZSTD_STORED_FIELDS_FEATURE_FLAG.isEnabled()) {
|
if (CodecService.ZSTD_STORED_FIELDS_FEATURE_FLAG.isEnabled()) {
|
||||||
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
|
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
|
||||||
assertThat(((PerFieldMapperCodec) codec).getPostingsFormatForField("field"), instanceOf(Completion99PostingsFormat.class));
|
assertThat(((PerFieldMapperCodec) codec).getPostingsFormatForField("field"), instanceOf(Completion912PostingsFormat.class));
|
||||||
} else {
|
} else {
|
||||||
if (codec instanceof CodecService.DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
|
if (codec instanceof CodecService.DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
|
||||||
codec = deduplicateFieldInfosCodec.delegate();
|
codec = deduplicateFieldInfosCodec.delegate();
|
||||||
|
@ -159,7 +159,7 @@ public class CompletionFieldMapperTests extends MapperTestCase {
|
||||||
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
|
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
|
||||||
assertThat(
|
assertThat(
|
||||||
((LegacyPerFieldMapperCodec) codec).getPostingsFormatForField("field"),
|
((LegacyPerFieldMapperCodec) codec).getPostingsFormatForField("field"),
|
||||||
instanceOf(Completion99PostingsFormat.class)
|
instanceOf(Completion912PostingsFormat.class)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.apache.lucene.search.BooleanClause;
|
||||||
import org.apache.lucene.search.BooleanQuery;
|
import org.apache.lucene.search.BooleanQuery;
|
||||||
import org.apache.lucene.search.ConstantScoreQuery;
|
import org.apache.lucene.search.ConstantScoreQuery;
|
||||||
import org.apache.lucene.search.FuzzyQuery;
|
import org.apache.lucene.search.FuzzyQuery;
|
||||||
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.PrefixQuery;
|
import org.apache.lucene.search.PrefixQuery;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.search.RegexpQuery;
|
import org.apache.lucene.search.RegexpQuery;
|
||||||
|
@ -231,20 +232,26 @@ public class ConstantScoreTextFieldTypeTests extends FieldTypeTestCase {
|
||||||
public void testPrefixIntervals() throws IOException {
|
public void testPrefixIntervals() throws IOException {
|
||||||
MappedFieldType ft = createFieldType();
|
MappedFieldType ft = createFieldType();
|
||||||
IntervalsSource prefixIntervals = ft.prefixIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
IntervalsSource prefixIntervals = ft.prefixIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
||||||
assertEquals(Intervals.prefix(new BytesRef("foo")), prefixIntervals);
|
assertEquals(Intervals.prefix(new BytesRef("foo"), IndexSearcher.getMaxClauseCount()), prefixIntervals);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWildcardIntervals() throws IOException {
|
public void testWildcardIntervals() throws IOException {
|
||||||
MappedFieldType ft = createFieldType();
|
MappedFieldType ft = createFieldType();
|
||||||
IntervalsSource wildcardIntervals = ft.wildcardIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
IntervalsSource wildcardIntervals = ft.wildcardIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
||||||
assertEquals(Intervals.wildcard(new BytesRef("foo")), wildcardIntervals);
|
assertEquals(Intervals.wildcard(new BytesRef("foo"), IndexSearcher.getMaxClauseCount()), wildcardIntervals);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRegexpIntervals() {
|
||||||
|
MappedFieldType ft = createFieldType();
|
||||||
|
IntervalsSource regexpIntervals = ft.regexpIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
||||||
|
assertEquals(Intervals.regexp(new BytesRef("foo"), IndexSearcher.getMaxClauseCount()), regexpIntervals);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFuzzyIntervals() throws IOException {
|
public void testFuzzyIntervals() throws IOException {
|
||||||
MappedFieldType ft = createFieldType();
|
MappedFieldType ft = createFieldType();
|
||||||
IntervalsSource fuzzyIntervals = ft.fuzzyIntervals("foo", 1, 2, true, MOCK_CONTEXT);
|
IntervalsSource fuzzyIntervals = ft.fuzzyIntervals("foo", 1, 2, true, MOCK_CONTEXT);
|
||||||
FuzzyQuery fq = new FuzzyQuery(new Term("field", "foo"), 1, 2, 128, true);
|
FuzzyQuery fq = new FuzzyQuery(new Term("field", "foo"), 1, 2, 128, true);
|
||||||
IntervalsSource expectedIntervals = Intervals.multiterm(fq.getAutomata(), "foo");
|
IntervalsSource expectedIntervals = Intervals.multiterm(fq.getAutomata(), IndexSearcher.getMaxClauseCount(), "foo");
|
||||||
assertEquals(expectedIntervals, fuzzyIntervals);
|
assertEquals(expectedIntervals, fuzzyIntervals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,6 +266,15 @@ public class ConstantScoreTextFieldTypeTests extends FieldTypeTestCase {
|
||||||
ConstantScoreTextFieldType ft = createFieldType();
|
ConstantScoreTextFieldType ft = createFieldType();
|
||||||
ft.setIndexPrefixes(1, 4);
|
ft.setIndexPrefixes(1, 4);
|
||||||
IntervalsSource wildcardIntervals = ft.wildcardIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
IntervalsSource wildcardIntervals = ft.wildcardIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
||||||
assertEquals(Intervals.wildcard(new BytesRef("foo")), wildcardIntervals);
|
assertEquals(Intervals.wildcard(new BytesRef("foo"), IndexSearcher.getMaxClauseCount()), wildcardIntervals);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRangeIntervals() {
|
||||||
|
MappedFieldType ft = createFieldType();
|
||||||
|
IntervalsSource rangeIntervals = ft.rangeIntervals(new BytesRef("foo"), new BytesRef("foo1"), true, true, MOCK_CONTEXT);
|
||||||
|
assertEquals(
|
||||||
|
Intervals.range(new BytesRef("foo"), new BytesRef("foo1"), true, true, IndexSearcher.getMaxClauseCount()),
|
||||||
|
rangeIntervals
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import org.apache.lucene.search.BooleanClause;
|
||||||
import org.apache.lucene.search.BooleanQuery;
|
import org.apache.lucene.search.BooleanQuery;
|
||||||
import org.apache.lucene.search.ConstantScoreQuery;
|
import org.apache.lucene.search.ConstantScoreQuery;
|
||||||
import org.apache.lucene.search.FuzzyQuery;
|
import org.apache.lucene.search.FuzzyQuery;
|
||||||
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.MultiTermQuery;
|
import org.apache.lucene.search.MultiTermQuery;
|
||||||
import org.apache.lucene.search.PrefixQuery;
|
import org.apache.lucene.search.PrefixQuery;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
|
@ -243,20 +244,26 @@ public class TextFieldTypeTests extends FieldTypeTestCase {
|
||||||
public void testPrefixIntervals() throws IOException {
|
public void testPrefixIntervals() throws IOException {
|
||||||
MappedFieldType ft = createFieldType();
|
MappedFieldType ft = createFieldType();
|
||||||
IntervalsSource prefixIntervals = ft.prefixIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
IntervalsSource prefixIntervals = ft.prefixIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
||||||
assertEquals(Intervals.prefix(new BytesRef("foo")), prefixIntervals);
|
assertEquals(Intervals.prefix(new BytesRef("foo"), IndexSearcher.getMaxClauseCount()), prefixIntervals);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWildcardIntervals() throws IOException {
|
public void testWildcardIntervals() {
|
||||||
MappedFieldType ft = createFieldType();
|
MappedFieldType ft = createFieldType();
|
||||||
IntervalsSource wildcardIntervals = ft.wildcardIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
IntervalsSource wildcardIntervals = ft.wildcardIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
||||||
assertEquals(Intervals.wildcard(new BytesRef("foo")), wildcardIntervals);
|
assertEquals(Intervals.wildcard(new BytesRef("foo"), IndexSearcher.getMaxClauseCount()), wildcardIntervals);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFuzzyIntervals() throws IOException {
|
public void testRegexpIntervals() {
|
||||||
|
MappedFieldType ft = createFieldType();
|
||||||
|
IntervalsSource regexpIntervals = ft.regexpIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
||||||
|
assertEquals(Intervals.regexp(new BytesRef("foo"), IndexSearcher.getMaxClauseCount()), regexpIntervals);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFuzzyIntervals() {
|
||||||
MappedFieldType ft = createFieldType();
|
MappedFieldType ft = createFieldType();
|
||||||
IntervalsSource fuzzyIntervals = ft.fuzzyIntervals("foo", 1, 2, true, MOCK_CONTEXT);
|
IntervalsSource fuzzyIntervals = ft.fuzzyIntervals("foo", 1, 2, true, MOCK_CONTEXT);
|
||||||
FuzzyQuery fq = new FuzzyQuery(new Term("field", "foo"), 1, 2, 128, true);
|
FuzzyQuery fq = new FuzzyQuery(new Term("field", "foo"), 1, 2, 128, true);
|
||||||
IntervalsSource expectedIntervals = Intervals.multiterm(fq.getAutomata(), "foo");
|
IntervalsSource expectedIntervals = Intervals.multiterm(fq.getAutomata(), IndexSearcher.getMaxClauseCount(), "foo");
|
||||||
assertEquals(expectedIntervals, fuzzyIntervals);
|
assertEquals(expectedIntervals, fuzzyIntervals);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,6 +278,15 @@ public class TextFieldTypeTests extends FieldTypeTestCase {
|
||||||
TextFieldType ft = createFieldType();
|
TextFieldType ft = createFieldType();
|
||||||
ft.setIndexPrefixes(1, 4);
|
ft.setIndexPrefixes(1, 4);
|
||||||
IntervalsSource wildcardIntervals = ft.wildcardIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
IntervalsSource wildcardIntervals = ft.wildcardIntervals(new BytesRef("foo"), MOCK_CONTEXT);
|
||||||
assertEquals(Intervals.wildcard(new BytesRef("foo")), wildcardIntervals);
|
assertEquals(Intervals.wildcard(new BytesRef("foo"), IndexSearcher.getMaxClauseCount()), wildcardIntervals);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRangeIntervals() {
|
||||||
|
MappedFieldType ft = createFieldType();
|
||||||
|
IntervalsSource rangeIntervals = ft.rangeIntervals(new BytesRef("foo"), new BytesRef("foo1"), true, true, MOCK_CONTEXT);
|
||||||
|
assertEquals(
|
||||||
|
Intervals.range(new BytesRef("foo"), new BytesRef("foo1"), true, true, IndexSearcher.getMaxClauseCount()),
|
||||||
|
rangeIntervals
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,14 +9,22 @@
|
||||||
|
|
||||||
package org.elasticsearch.index.query;
|
package org.elasticsearch.index.query;
|
||||||
|
|
||||||
|
import org.apache.lucene.analysis.core.KeywordAnalyzer;
|
||||||
|
import org.apache.lucene.document.Field;
|
||||||
|
import org.apache.lucene.document.TextField;
|
||||||
|
import org.apache.lucene.index.IndexReader;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.queries.intervals.IntervalQuery;
|
import org.apache.lucene.queries.intervals.IntervalQuery;
|
||||||
import org.apache.lucene.queries.intervals.Intervals;
|
import org.apache.lucene.queries.intervals.Intervals;
|
||||||
import org.apache.lucene.queries.intervals.IntervalsSource;
|
import org.apache.lucene.queries.intervals.IntervalsSource;
|
||||||
import org.apache.lucene.search.BoostQuery;
|
import org.apache.lucene.search.BoostQuery;
|
||||||
import org.apache.lucene.search.FuzzyQuery;
|
import org.apache.lucene.search.FuzzyQuery;
|
||||||
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.MatchNoDocsQuery;
|
import org.apache.lucene.search.MatchNoDocsQuery;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
|
import org.apache.lucene.search.ScoreMode;
|
||||||
|
import org.apache.lucene.store.Directory;
|
||||||
|
import org.apache.lucene.tests.index.RandomIndexWriter;
|
||||||
import org.apache.lucene.util.BytesRef;
|
import org.apache.lucene.util.BytesRef;
|
||||||
import org.elasticsearch.common.ParsingException;
|
import org.elasticsearch.common.ParsingException;
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
|
@ -34,7 +42,9 @@ import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.util.Collections.singleton;
|
||||||
import static org.elasticsearch.xcontent.XContentFactory.jsonBuilder;
|
import static org.elasticsearch.xcontent.XContentFactory.jsonBuilder;
|
||||||
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.hamcrest.Matchers.instanceOf;
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
|
|
||||||
|
@ -606,7 +616,7 @@ public class IntervalQueryBuilderTests extends AbstractQueryTestCase<IntervalQue
|
||||||
}
|
}
|
||||||
}""", TEXT_FIELD_NAME);
|
}""", TEXT_FIELD_NAME);
|
||||||
IntervalQueryBuilder builder = (IntervalQueryBuilder) parseQuery(json);
|
IntervalQueryBuilder builder = (IntervalQueryBuilder) parseQuery(json);
|
||||||
Query expected = new IntervalQuery(TEXT_FIELD_NAME, Intervals.prefix(new BytesRef("term")));
|
Query expected = new IntervalQuery(TEXT_FIELD_NAME, Intervals.prefix(new BytesRef("term"), IndexSearcher.getMaxClauseCount()));
|
||||||
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
||||||
|
|
||||||
String no_positions_json = Strings.format("""
|
String no_positions_json = Strings.format("""
|
||||||
|
@ -667,7 +677,13 @@ public class IntervalQueryBuilderTests extends AbstractQueryTestCase<IntervalQue
|
||||||
builder = (IntervalQueryBuilder) parseQuery(short_prefix_json);
|
builder = (IntervalQueryBuilder) parseQuery(short_prefix_json);
|
||||||
expected = new IntervalQuery(
|
expected = new IntervalQuery(
|
||||||
PREFIXED_FIELD,
|
PREFIXED_FIELD,
|
||||||
Intervals.or(Intervals.fixField(PREFIXED_FIELD + "._index_prefix", Intervals.wildcard(new BytesRef("t?"))), Intervals.term("t"))
|
Intervals.or(
|
||||||
|
Intervals.fixField(
|
||||||
|
PREFIXED_FIELD + "._index_prefix",
|
||||||
|
Intervals.wildcard(new BytesRef("t?"), IndexSearcher.getMaxClauseCount())
|
||||||
|
),
|
||||||
|
Intervals.term("t")
|
||||||
|
)
|
||||||
);
|
);
|
||||||
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
||||||
|
|
||||||
|
@ -726,8 +742,109 @@ public class IntervalQueryBuilderTests extends AbstractQueryTestCase<IntervalQue
|
||||||
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWildcard() throws IOException {
|
public void testRegexp() throws IOException {
|
||||||
|
String json = Strings.format("""
|
||||||
|
{
|
||||||
|
"intervals": {
|
||||||
|
"%s": {
|
||||||
|
"regexp": {
|
||||||
|
"pattern": "Te.*m"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}""", TEXT_FIELD_NAME);
|
||||||
|
|
||||||
|
IntervalQueryBuilder builder = (IntervalQueryBuilder) parseQuery(json);
|
||||||
|
Query expected = new IntervalQuery(TEXT_FIELD_NAME, Intervals.regexp(new BytesRef("te.*m"), IndexSearcher.getMaxClauseCount()));
|
||||||
|
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
||||||
|
|
||||||
|
String no_positions_json = Strings.format("""
|
||||||
|
{
|
||||||
|
"intervals": {
|
||||||
|
"%s": {
|
||||||
|
"regexp": {
|
||||||
|
"pattern": "Te.*m"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""", NO_POSITIONS_FIELD);
|
||||||
|
expectThrows(IllegalArgumentException.class, () -> {
|
||||||
|
IntervalQueryBuilder builder1 = (IntervalQueryBuilder) parseQuery(no_positions_json);
|
||||||
|
builder1.toQuery(createSearchExecutionContext());
|
||||||
|
});
|
||||||
|
|
||||||
|
String fixed_field_json = Strings.format("""
|
||||||
|
{
|
||||||
|
"intervals": {
|
||||||
|
"%s": {
|
||||||
|
"regexp": {
|
||||||
|
"pattern": "Te.*m",
|
||||||
|
"use_field": "masked_field"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}""", TEXT_FIELD_NAME);
|
||||||
|
|
||||||
|
builder = (IntervalQueryBuilder) parseQuery(fixed_field_json);
|
||||||
|
expected = new IntervalQuery(
|
||||||
|
TEXT_FIELD_NAME,
|
||||||
|
Intervals.fixField(MASKED_FIELD, Intervals.regexp(new BytesRef("te.*m"), IndexSearcher.getMaxClauseCount()))
|
||||||
|
);
|
||||||
|
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
||||||
|
|
||||||
|
String fixed_field_json_no_positions = Strings.format("""
|
||||||
|
{
|
||||||
|
"intervals": {
|
||||||
|
"%s": {
|
||||||
|
"regexp": {
|
||||||
|
"pattern": "Te.*m",
|
||||||
|
"use_field": "%s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}""", TEXT_FIELD_NAME, NO_POSITIONS_FIELD);
|
||||||
|
expectThrows(IllegalArgumentException.class, () -> {
|
||||||
|
IntervalQueryBuilder builder1 = (IntervalQueryBuilder) parseQuery(fixed_field_json_no_positions);
|
||||||
|
builder1.toQuery(createSearchExecutionContext());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMaxExpansionExceptionFailure() throws Exception {
|
||||||
|
IntervalsSourceProvider provider1 = new IntervalsSourceProvider.Prefix("bar", "keyword", null);
|
||||||
|
IntervalsSourceProvider provider2 = new IntervalsSourceProvider.Wildcard("bar*", "keyword", null);
|
||||||
|
IntervalsSourceProvider provider3 = new IntervalsSourceProvider.Fuzzy("bar", 0, true, Fuzziness.fromEdits(1), "keyword", null);
|
||||||
|
IntervalsSourceProvider provider4 = new IntervalsSourceProvider.Regexp("bar.*", "keyword", null);
|
||||||
|
IntervalsSourceProvider provider5 = new IntervalsSourceProvider.Range("bar", "bar2", true, true, "keyword", null);
|
||||||
|
IntervalsSourceProvider provider = randomFrom(provider1, provider2, provider3, provider4, provider5);
|
||||||
|
|
||||||
|
try (Directory directory = newDirectory()) {
|
||||||
|
try (RandomIndexWriter iw = new RandomIndexWriter(random(), directory, new KeywordAnalyzer())) {
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
iw.addDocument(singleton(new TextField(TEXT_FIELD_NAME, "bar" + i, Field.Store.NO)));
|
||||||
|
}
|
||||||
|
try (IndexReader reader = iw.getReader()) {
|
||||||
|
int origBoolMaxClauseCount = IndexSearcher.getMaxClauseCount();
|
||||||
|
IndexSearcher.setMaxClauseCount(1);
|
||||||
|
try {
|
||||||
|
|
||||||
|
IntervalQueryBuilder queryBuilder = new IntervalQueryBuilder(TEXT_FIELD_NAME, provider);
|
||||||
|
IndexSearcher searcher = newSearcher(reader);
|
||||||
|
Query query = queryBuilder.toQuery(createSearchExecutionContext(searcher));
|
||||||
|
RuntimeException exc = expectThrows(
|
||||||
|
RuntimeException.class,
|
||||||
|
() -> query.createWeight(searcher, ScoreMode.COMPLETE, 1.0f).scorer(searcher.getLeafContexts().get(0))
|
||||||
|
);
|
||||||
|
assertThat(exc.getMessage(), containsString("expanded to too many terms (limit 1)"));
|
||||||
|
} finally {
|
||||||
|
IndexSearcher.setMaxClauseCount(origBoolMaxClauseCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWildcard() throws IOException {
|
||||||
String json = Strings.format("""
|
String json = Strings.format("""
|
||||||
{
|
{
|
||||||
"intervals": {
|
"intervals": {
|
||||||
|
@ -740,7 +857,7 @@ public class IntervalQueryBuilderTests extends AbstractQueryTestCase<IntervalQue
|
||||||
}""", TEXT_FIELD_NAME);
|
}""", TEXT_FIELD_NAME);
|
||||||
|
|
||||||
IntervalQueryBuilder builder = (IntervalQueryBuilder) parseQuery(json);
|
IntervalQueryBuilder builder = (IntervalQueryBuilder) parseQuery(json);
|
||||||
Query expected = new IntervalQuery(TEXT_FIELD_NAME, Intervals.wildcard(new BytesRef("te?m")));
|
Query expected = new IntervalQuery(TEXT_FIELD_NAME, Intervals.wildcard(new BytesRef("te?m"), IndexSearcher.getMaxClauseCount()));
|
||||||
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
||||||
|
|
||||||
String no_positions_json = Strings.format("""
|
String no_positions_json = Strings.format("""
|
||||||
|
@ -772,7 +889,7 @@ public class IntervalQueryBuilderTests extends AbstractQueryTestCase<IntervalQue
|
||||||
}""", TEXT_FIELD_NAME);
|
}""", TEXT_FIELD_NAME);
|
||||||
|
|
||||||
builder = (IntervalQueryBuilder) parseQuery(keyword_json);
|
builder = (IntervalQueryBuilder) parseQuery(keyword_json);
|
||||||
expected = new IntervalQuery(TEXT_FIELD_NAME, Intervals.wildcard(new BytesRef("Te?m")));
|
expected = new IntervalQuery(TEXT_FIELD_NAME, Intervals.wildcard(new BytesRef("Te?m"), IndexSearcher.getMaxClauseCount()));
|
||||||
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
||||||
|
|
||||||
String fixed_field_json = Strings.format("""
|
String fixed_field_json = Strings.format("""
|
||||||
|
@ -788,7 +905,10 @@ public class IntervalQueryBuilderTests extends AbstractQueryTestCase<IntervalQue
|
||||||
}""", TEXT_FIELD_NAME);
|
}""", TEXT_FIELD_NAME);
|
||||||
|
|
||||||
builder = (IntervalQueryBuilder) parseQuery(fixed_field_json);
|
builder = (IntervalQueryBuilder) parseQuery(fixed_field_json);
|
||||||
expected = new IntervalQuery(TEXT_FIELD_NAME, Intervals.fixField(MASKED_FIELD, Intervals.wildcard(new BytesRef("te?m"))));
|
expected = new IntervalQuery(
|
||||||
|
TEXT_FIELD_NAME,
|
||||||
|
Intervals.fixField(MASKED_FIELD, Intervals.wildcard(new BytesRef("te?m"), IndexSearcher.getMaxClauseCount()))
|
||||||
|
);
|
||||||
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
||||||
|
|
||||||
String fixed_field_json_no_positions = Strings.format("""
|
String fixed_field_json_no_positions = Strings.format("""
|
||||||
|
@ -821,13 +941,22 @@ public class IntervalQueryBuilderTests extends AbstractQueryTestCase<IntervalQue
|
||||||
}""", TEXT_FIELD_NAME);
|
}""", TEXT_FIELD_NAME);
|
||||||
|
|
||||||
builder = (IntervalQueryBuilder) parseQuery(fixed_field_analyzer_json);
|
builder = (IntervalQueryBuilder) parseQuery(fixed_field_analyzer_json);
|
||||||
expected = new IntervalQuery(TEXT_FIELD_NAME, Intervals.fixField(MASKED_FIELD, Intervals.wildcard(new BytesRef("Te?m"))));
|
expected = new IntervalQuery(
|
||||||
|
TEXT_FIELD_NAME,
|
||||||
|
Intervals.fixField(MASKED_FIELD, Intervals.wildcard(new BytesRef("Te?m"), IndexSearcher.getMaxClauseCount()))
|
||||||
|
);
|
||||||
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IntervalsSource buildFuzzySource(String term, String label, int prefixLength, boolean transpositions, int editDistance) {
|
private static IntervalsSource buildFuzzySource(String term, String label, int prefixLength, boolean transpositions, int editDistance) {
|
||||||
FuzzyQuery fq = new FuzzyQuery(new Term("field", term), editDistance, prefixLength, 128, transpositions);
|
FuzzyQuery fq = new FuzzyQuery(
|
||||||
return Intervals.multiterm(fq.getAutomata(), label);
|
new Term("field", term),
|
||||||
|
editDistance,
|
||||||
|
prefixLength,
|
||||||
|
IndexSearcher.getMaxClauseCount(),
|
||||||
|
transpositions
|
||||||
|
);
|
||||||
|
return Intervals.multiterm(fq.getAutomata(), IndexSearcher.getMaxClauseCount(), label);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFuzzy() throws IOException {
|
public void testFuzzy() throws IOException {
|
||||||
|
@ -932,7 +1061,77 @@ public class IntervalQueryBuilderTests extends AbstractQueryTestCase<IntervalQue
|
||||||
Intervals.fixField(MASKED_FIELD, buildFuzzySource("term", "term", 2, true, Fuzziness.ONE.asDistance("term")))
|
Intervals.fixField(MASKED_FIELD, buildFuzzySource("term", "term", 2, true, Fuzziness.ONE.asDistance("term")))
|
||||||
);
|
);
|
||||||
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testRange() throws IOException {
|
||||||
|
String json = Strings.format("""
|
||||||
|
{
|
||||||
|
"intervals": {
|
||||||
|
"%s": {
|
||||||
|
"range": {
|
||||||
|
"gte": "aaa",
|
||||||
|
"lte": "aab"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}""", TEXT_FIELD_NAME);
|
||||||
|
IntervalQueryBuilder builder = (IntervalQueryBuilder) parseQuery(json);
|
||||||
|
Query expected = new IntervalQuery(
|
||||||
|
TEXT_FIELD_NAME,
|
||||||
|
Intervals.range(new BytesRef("aaa"), new BytesRef("aab"), true, true, IndexSearcher.getMaxClauseCount())
|
||||||
|
);
|
||||||
|
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
||||||
|
|
||||||
|
json = Strings.format("""
|
||||||
|
{
|
||||||
|
"intervals": {
|
||||||
|
"%s": {
|
||||||
|
"range": {
|
||||||
|
"gt": "aaa",
|
||||||
|
"lt": "aab"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}""", TEXT_FIELD_NAME);
|
||||||
|
builder = (IntervalQueryBuilder) parseQuery(json);
|
||||||
|
expected = new IntervalQuery(
|
||||||
|
TEXT_FIELD_NAME,
|
||||||
|
Intervals.range(new BytesRef("aaa"), new BytesRef("aab"), false, false, IndexSearcher.getMaxClauseCount())
|
||||||
|
);
|
||||||
|
assertEquals(expected, builder.toQuery(createSearchExecutionContext()));
|
||||||
|
|
||||||
|
String incomplete_range = Strings.format("""
|
||||||
|
{
|
||||||
|
"intervals": {
|
||||||
|
"%s": {
|
||||||
|
"range": {
|
||||||
|
"gt": "aaa"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""", TEXT_FIELD_NAME);
|
||||||
|
IllegalArgumentException exc = expectThrows(IllegalArgumentException.class, () -> {
|
||||||
|
IntervalQueryBuilder builder1 = (IntervalQueryBuilder) parseQuery(incomplete_range);
|
||||||
|
builder1.toQuery(createSearchExecutionContext());
|
||||||
|
});
|
||||||
|
assertEquals("Either [lte] or [lt], one of them must be provided", exc.getCause().getMessage());
|
||||||
|
|
||||||
|
String incomplete_range2 = Strings.format("""
|
||||||
|
{
|
||||||
|
"intervals": {
|
||||||
|
"%s": {
|
||||||
|
"range": {
|
||||||
|
"lt": "aaa"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""", TEXT_FIELD_NAME);
|
||||||
|
exc = expectThrows(IllegalArgumentException.class, () -> {
|
||||||
|
IntervalQueryBuilder builder1 = (IntervalQueryBuilder) parseQuery(incomplete_range2);
|
||||||
|
builder1.toQuery(createSearchExecutionContext());
|
||||||
|
});
|
||||||
|
assertEquals("Either [gte] or [gt], one of them must be provided", exc.getCause().getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the "Elastic License
|
||||||
|
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||||
|
* Public License v 1"; you may not use this file except in compliance with, at
|
||||||
|
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||||
|
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.index.query;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.io.stream.Writeable;
|
||||||
|
import org.elasticsearch.test.AbstractXContentSerializingTestCase;
|
||||||
|
import org.elasticsearch.xcontent.XContentParser;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.elasticsearch.index.query.IntervalsSourceProvider.Range;
|
||||||
|
|
||||||
|
public class RangeIntervalsSourceProviderTests extends AbstractXContentSerializingTestCase<Range> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Range createTestInstance() {
|
||||||
|
return createRandomRange();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Range createRandomRange() {
|
||||||
|
return new Range(
|
||||||
|
"a" + randomAlphaOfLengthBetween(1, 10),
|
||||||
|
"z" + randomAlphaOfLengthBetween(1, 10),
|
||||||
|
randomBoolean(),
|
||||||
|
randomBoolean(),
|
||||||
|
randomBoolean() ? randomAlphaOfLength(10) : null,
|
||||||
|
randomBoolean() ? randomAlphaOfLength(10) : null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Range mutateInstance(Range instance) {
|
||||||
|
String lowerTerm = instance.getLowerTerm();
|
||||||
|
String upperTerm = instance.getUpperTerm();
|
||||||
|
boolean includeLower = instance.getIncludeLower();
|
||||||
|
boolean includeUpper = instance.getIncludeUpper();
|
||||||
|
String analyzer = instance.getAnalyzer();
|
||||||
|
String useField = instance.getUseField();
|
||||||
|
switch (between(0, 5)) {
|
||||||
|
case 0 -> lowerTerm = "a" + lowerTerm;
|
||||||
|
case 1 -> upperTerm = "z" + upperTerm;
|
||||||
|
case 2 -> includeLower = includeLower == false;
|
||||||
|
case 3 -> includeUpper = includeUpper == false;
|
||||||
|
case 4 -> analyzer = randomAlphaOfLength(5);
|
||||||
|
case 5 -> useField = useField == null ? randomAlphaOfLength(5) : null;
|
||||||
|
}
|
||||||
|
return new Range(lowerTerm, upperTerm, includeLower, includeUpper, analyzer, useField);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Writeable.Reader<Range> instanceReader() {
|
||||||
|
return Range::new;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Range doParseInstance(XContentParser parser) throws IOException {
|
||||||
|
if (parser.nextToken() == XContentParser.Token.START_OBJECT) {
|
||||||
|
parser.nextToken();
|
||||||
|
}
|
||||||
|
Range range = (Range) IntervalsSourceProvider.fromXContent(parser);
|
||||||
|
assertEquals(XContentParser.Token.END_OBJECT, parser.nextToken());
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the "Elastic License
|
||||||
|
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
||||||
|
* Public License v 1"; you may not use this file except in compliance with, at
|
||||||
|
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
||||||
|
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.index.query;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.io.stream.Writeable;
|
||||||
|
import org.elasticsearch.test.AbstractXContentSerializingTestCase;
|
||||||
|
import org.elasticsearch.xcontent.XContentParser;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.elasticsearch.index.query.IntervalsSourceProvider.Regexp;
|
||||||
|
|
||||||
|
public class RegexpIntervalsSourceProviderTests extends AbstractXContentSerializingTestCase<Regexp> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Regexp createTestInstance() {
|
||||||
|
return createRandomRegexp();
|
||||||
|
}
|
||||||
|
|
||||||
|
static Regexp createRandomRegexp() {
|
||||||
|
return new Regexp(
|
||||||
|
randomAlphaOfLengthBetween(1, 10),
|
||||||
|
randomBoolean() ? randomAlphaOfLength(10) : null,
|
||||||
|
randomBoolean() ? randomAlphaOfLength(10) : null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Regexp mutateInstance(Regexp instance) {
|
||||||
|
String regexp = instance.getPattern();
|
||||||
|
String analyzer = instance.getAnalyzer();
|
||||||
|
String useField = instance.getUseField();
|
||||||
|
switch (between(0, 2)) {
|
||||||
|
case 0 -> regexp += "a";
|
||||||
|
case 1 -> analyzer = randomAlphaOfLength(5);
|
||||||
|
case 2 -> useField = useField == null ? randomAlphaOfLength(5) : null;
|
||||||
|
}
|
||||||
|
return new Regexp(regexp, analyzer, useField);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Writeable.Reader<Regexp> instanceReader() {
|
||||||
|
return Regexp::new;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Regexp doParseInstance(XContentParser parser) throws IOException {
|
||||||
|
if (parser.nextToken() == XContentParser.Token.START_OBJECT) {
|
||||||
|
parser.nextToken();
|
||||||
|
}
|
||||||
|
Regexp regexp = (Regexp) IntervalsSourceProvider.fromXContent(parser);
|
||||||
|
assertEquals(XContentParser.Token.END_OBJECT, parser.nextToken());
|
||||||
|
return regexp;
|
||||||
|
}
|
||||||
|
}
|
|
@ -274,7 +274,7 @@ public class StoreTests extends ESTestCase {
|
||||||
metadata = store.getMetadata(randomBoolean() ? indexCommit : null);
|
metadata = store.getMetadata(randomBoolean() ? indexCommit : null);
|
||||||
assertThat(metadata.fileMetadataMap().isEmpty(), is(false));
|
assertThat(metadata.fileMetadataMap().isEmpty(), is(false));
|
||||||
for (StoreFileMetadata meta : metadata) {
|
for (StoreFileMetadata meta : metadata) {
|
||||||
try (IndexInput input = store.directory().openInput(meta.name(), IOContext.DEFAULT)) {
|
try (IndexInput input = store.directory().openInput(meta.name(), IOContext.READONCE)) {
|
||||||
String checksum = Store.digestToString(CodecUtil.retrieveChecksum(input));
|
String checksum = Store.digestToString(CodecUtil.retrieveChecksum(input));
|
||||||
assertThat("File: " + meta.name() + " has a different checksum", meta.checksum(), equalTo(checksum));
|
assertThat("File: " + meta.name() + " has a different checksum", meta.checksum(), equalTo(checksum));
|
||||||
assertThat(meta.writtenBy(), equalTo(Version.LATEST.toString()));
|
assertThat(meta.writtenBy(), equalTo(Version.LATEST.toString()));
|
||||||
|
|
|
@ -2742,13 +2742,13 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify that a single slice is created for requests that don't support parallel collection, while computation
|
* Verify that a single slice is created for requests that don't support parallel collection, while an executor is still
|
||||||
* is still offloaded to the worker threads. Also ensure multiple slices are created for requests that do support
|
* provided to the searcher to parallelize other operations. Also ensure multiple slices are created for requests that do support
|
||||||
* parallel collection.
|
* parallel collection.
|
||||||
*/
|
*/
|
||||||
public void testSlicingBehaviourForParallelCollection() throws Exception {
|
public void testSlicingBehaviourForParallelCollection() throws Exception {
|
||||||
IndexService indexService = createIndex("index", Settings.EMPTY);
|
IndexService indexService = createIndex("index", Settings.EMPTY);
|
||||||
ThreadPoolExecutor executor = (ThreadPoolExecutor) indexService.getThreadPool().executor(ThreadPool.Names.SEARCH_WORKER);
|
ThreadPoolExecutor executor = (ThreadPoolExecutor) indexService.getThreadPool().executor(ThreadPool.Names.SEARCH);
|
||||||
final int configuredMaxPoolSize = 10;
|
final int configuredMaxPoolSize = 10;
|
||||||
executor.setMaximumPoolSize(configuredMaxPoolSize); // We set this explicitly to be independent of CPU cores.
|
executor.setMaximumPoolSize(configuredMaxPoolSize); // We set this explicitly to be independent of CPU cores.
|
||||||
int numDocs = randomIntBetween(50, 100);
|
int numDocs = randomIntBetween(50, 100);
|
||||||
|
@ -2799,7 +2799,7 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
||||||
assertBusy(
|
assertBusy(
|
||||||
() -> assertEquals(
|
() -> assertEquals(
|
||||||
"DFS supports parallel collection, so the number of slices should be > 1.",
|
"DFS supports parallel collection, so the number of slices should be > 1.",
|
||||||
expectedSlices,
|
expectedSlices - 1, // one slice executes on the calling thread
|
||||||
executor.getCompletedTaskCount() - priorExecutorTaskCount
|
executor.getCompletedTaskCount() - priorExecutorTaskCount
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -2829,7 +2829,7 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
||||||
assertBusy(
|
assertBusy(
|
||||||
() -> assertEquals(
|
() -> assertEquals(
|
||||||
"QUERY supports parallel collection when enabled, so the number of slices should be > 1.",
|
"QUERY supports parallel collection when enabled, so the number of slices should be > 1.",
|
||||||
expectedSlices,
|
expectedSlices - 1, // one slice executes on the calling thread
|
||||||
executor.getCompletedTaskCount() - priorExecutorTaskCount
|
executor.getCompletedTaskCount() - priorExecutorTaskCount
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -2838,13 +2838,14 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
||||||
{
|
{
|
||||||
try (SearchContext searchContext = service.createContext(readerContext, request, task, ResultsType.FETCH, true)) {
|
try (SearchContext searchContext = service.createContext(readerContext, request, task, ResultsType.FETCH, true)) {
|
||||||
ContextIndexSearcher searcher = searchContext.searcher();
|
ContextIndexSearcher searcher = searchContext.searcher();
|
||||||
assertNotNull(searcher.getExecutor());
|
assertNull(searcher.getExecutor());
|
||||||
final long priorExecutorTaskCount = executor.getCompletedTaskCount();
|
final long priorExecutorTaskCount = executor.getCompletedTaskCount();
|
||||||
searcher.search(termQuery, new TotalHitCountCollectorManager());
|
searcher.search(termQuery, new TotalHitCountCollectorManager());
|
||||||
assertBusy(
|
assertBusy(
|
||||||
() -> assertEquals(
|
() -> assertEquals(
|
||||||
"The number of slices should be 1 as FETCH does not support parallel collection.",
|
"The number of slices should be 1 as FETCH does not support parallel collection and thus runs on the calling"
|
||||||
1,
|
+ " thread.",
|
||||||
|
0,
|
||||||
executor.getCompletedTaskCount() - priorExecutorTaskCount
|
executor.getCompletedTaskCount() - priorExecutorTaskCount
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -2853,13 +2854,13 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
||||||
{
|
{
|
||||||
try (SearchContext searchContext = service.createContext(readerContext, request, task, ResultsType.NONE, true)) {
|
try (SearchContext searchContext = service.createContext(readerContext, request, task, ResultsType.NONE, true)) {
|
||||||
ContextIndexSearcher searcher = searchContext.searcher();
|
ContextIndexSearcher searcher = searchContext.searcher();
|
||||||
assertNotNull(searcher.getExecutor());
|
assertNull(searcher.getExecutor());
|
||||||
final long priorExecutorTaskCount = executor.getCompletedTaskCount();
|
final long priorExecutorTaskCount = executor.getCompletedTaskCount();
|
||||||
searcher.search(termQuery, new TotalHitCountCollectorManager());
|
searcher.search(termQuery, new TotalHitCountCollectorManager());
|
||||||
assertBusy(
|
assertBusy(
|
||||||
() -> assertEquals(
|
() -> assertEquals(
|
||||||
"The number of slices should be 1 as NONE does not support parallel collection.",
|
"The number of slices should be 1 as NONE does not support parallel collection.",
|
||||||
1,
|
0, // zero since one slice executes on the calling thread
|
||||||
executor.getCompletedTaskCount() - priorExecutorTaskCount
|
executor.getCompletedTaskCount() - priorExecutorTaskCount
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -2876,13 +2877,13 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
||||||
{
|
{
|
||||||
try (SearchContext searchContext = service.createContext(readerContext, request, task, ResultsType.QUERY, true)) {
|
try (SearchContext searchContext = service.createContext(readerContext, request, task, ResultsType.QUERY, true)) {
|
||||||
ContextIndexSearcher searcher = searchContext.searcher();
|
ContextIndexSearcher searcher = searchContext.searcher();
|
||||||
assertNotNull(searcher.getExecutor());
|
assertNull(searcher.getExecutor());
|
||||||
final long priorExecutorTaskCount = executor.getCompletedTaskCount();
|
final long priorExecutorTaskCount = executor.getCompletedTaskCount();
|
||||||
searcher.search(termQuery, new TotalHitCountCollectorManager());
|
searcher.search(termQuery, new TotalHitCountCollectorManager());
|
||||||
assertBusy(
|
assertBusy(
|
||||||
() -> assertEquals(
|
() -> assertEquals(
|
||||||
"The number of slices should be 1 when QUERY parallel collection is disabled.",
|
"The number of slices should be 1 when QUERY parallel collection is disabled.",
|
||||||
1,
|
0, // zero since one slice executes on the calling thread
|
||||||
executor.getCompletedTaskCount() - priorExecutorTaskCount
|
executor.getCompletedTaskCount() - priorExecutorTaskCount
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -2919,7 +2920,7 @@ public class SearchServiceTests extends ESSingleNodeTestCase {
|
||||||
assertBusy(
|
assertBusy(
|
||||||
() -> assertEquals(
|
() -> assertEquals(
|
||||||
"QUERY supports parallel collection when enabled, so the number of slices should be > 1.",
|
"QUERY supports parallel collection when enabled, so the number of slices should be > 1.",
|
||||||
expectedSlices,
|
expectedSlices - 1, // one slice executes on the calling thread
|
||||||
executor.getCompletedTaskCount() - priorExecutorTaskCount
|
executor.getCompletedTaskCount() - priorExecutorTaskCount
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class DfsPhaseTests extends ESTestCase {
|
||||||
@Before
|
@Before
|
||||||
public final void init() {
|
public final void init() {
|
||||||
threadPool = new TestThreadPool(DfsPhaseTests.class.getName());
|
threadPool = new TestThreadPool(DfsPhaseTests.class.getName());
|
||||||
threadPoolExecutor = (ThreadPoolExecutor) threadPool.executor(ThreadPool.Names.SEARCH_WORKER);
|
threadPoolExecutor = (ThreadPoolExecutor) threadPool.executor(ThreadPool.Names.SEARCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
|
|
@ -224,7 +224,8 @@ public class ContextIndexSearcherTests extends ESTestCase {
|
||||||
int numSegments = directoryReader.getContext().leaves().size();
|
int numSegments = directoryReader.getContext().leaves().size();
|
||||||
KnnFloatVectorQuery vectorQuery = new KnnFloatVectorQuery("float_vector", new float[] { 0, 0, 0 }, 10, null);
|
KnnFloatVectorQuery vectorQuery = new KnnFloatVectorQuery("float_vector", new float[] { 0, 0, 0 }, 10, null);
|
||||||
vectorQuery.rewrite(searcher);
|
vectorQuery.rewrite(searcher);
|
||||||
assertBusy(() -> assertEquals(numSegments, executor.getCompletedTaskCount()));
|
// 1 task gets executed on the caller thread
|
||||||
|
assertBusy(() -> assertEquals(numSegments - 1, executor.getCompletedTaskCount()));
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
terminate(executor);
|
terminate(executor);
|
||||||
|
@ -253,8 +254,9 @@ public class ContextIndexSearcherTests extends ESTestCase {
|
||||||
Integer totalHits = searcher.search(new MatchAllDocsQuery(), new TotalHitCountCollectorManager());
|
Integer totalHits = searcher.search(new MatchAllDocsQuery(), new TotalHitCountCollectorManager());
|
||||||
assertEquals(numDocs, totalHits.intValue());
|
assertEquals(numDocs, totalHits.intValue());
|
||||||
int numExpectedTasks = ContextIndexSearcher.computeSlices(searcher.getIndexReader().leaves(), Integer.MAX_VALUE, 1).length;
|
int numExpectedTasks = ContextIndexSearcher.computeSlices(searcher.getIndexReader().leaves(), Integer.MAX_VALUE, 1).length;
|
||||||
// check that each slice goes to the executor, no matter the queue size or the number of slices
|
// check that each slice except for one that executes on the calling thread goes to the executor, no matter the queue size
|
||||||
assertBusy(() -> assertEquals(numExpectedTasks, executor.getCompletedTaskCount()));
|
// or the number of slices
|
||||||
|
assertBusy(() -> assertEquals(numExpectedTasks - 1, executor.getCompletedTaskCount()));
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
terminate(executor);
|
terminate(executor);
|
||||||
|
|
|
@ -1850,8 +1850,6 @@ public class SnapshotResiliencyTests extends ESTestCase {
|
||||||
Settings.builder()
|
Settings.builder()
|
||||||
.put(NODE_NAME_SETTING.getKey(), nodeName)
|
.put(NODE_NAME_SETTING.getKey(), nodeName)
|
||||||
.put(PATH_HOME_SETTING.getKey(), tempDir.resolve(nodeName).toAbsolutePath())
|
.put(PATH_HOME_SETTING.getKey(), tempDir.resolve(nodeName).toAbsolutePath())
|
||||||
// test uses the same executor service for all thread pools, search worker would need to be a different one
|
|
||||||
.put(SearchService.SEARCH_WORKER_THREADS_ENABLED.getKey(), false)
|
|
||||||
.put(Environment.PATH_REPO_SETTING.getKey(), tempDir.resolve("repo").toAbsolutePath())
|
.put(Environment.PATH_REPO_SETTING.getKey(), tempDir.resolve("repo").toAbsolutePath())
|
||||||
.putList(
|
.putList(
|
||||||
ClusterBootstrapService.INITIAL_MASTER_NODES_SETTING.getKey(),
|
ClusterBootstrapService.INITIAL_MASTER_NODES_SETTING.getKey(),
|
||||||
|
|
|
@ -25,8 +25,6 @@ import org.elasticsearch.test.MockLog;
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.LinkedTransferQueue;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import static org.elasticsearch.common.util.concurrent.EsExecutors.TaskTrackingConfig.DEFAULT;
|
import static org.elasticsearch.common.util.concurrent.EsExecutors.TaskTrackingConfig.DEFAULT;
|
||||||
|
@ -371,25 +369,6 @@ public class ThreadPoolTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testSearchWorkedThreadPool() {
|
|
||||||
final int allocatedProcessors = randomIntBetween(1, EsExecutors.allocatedProcessors(Settings.EMPTY));
|
|
||||||
final ThreadPool threadPool = new TestThreadPool(
|
|
||||||
"test",
|
|
||||||
Settings.builder().put(EsExecutors.NODE_PROCESSORS_SETTING.getKey(), allocatedProcessors).build()
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
ExecutorService executor = threadPool.executor(ThreadPool.Names.SEARCH_WORKER);
|
|
||||||
assertThat(executor, instanceOf(ThreadPoolExecutor.class));
|
|
||||||
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
|
|
||||||
int expectedPoolSize = allocatedProcessors * 3 / 2 + 1;
|
|
||||||
assertEquals(expectedPoolSize, threadPoolExecutor.getCorePoolSize());
|
|
||||||
assertEquals(expectedPoolSize, threadPoolExecutor.getMaximumPoolSize());
|
|
||||||
assertThat(threadPoolExecutor.getQueue(), instanceOf(LinkedTransferQueue.class));
|
|
||||||
} finally {
|
|
||||||
assertTrue(terminate(threadPool));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testScheduledOneShotRejection() {
|
public void testScheduledOneShotRejection() {
|
||||||
final var name = "fixed-bounded";
|
final var name = "fixed-bounded";
|
||||||
final var threadPool = new TestThreadPool(
|
final var threadPool = new TestThreadPool(
|
||||||
|
|
|
@ -212,7 +212,7 @@ public abstract class AggregatorTestCase extends ESTestCase {
|
||||||
@Before
|
@Before
|
||||||
public final void initPlugins() {
|
public final void initPlugins() {
|
||||||
threadPool = new TestThreadPool(AggregatorTestCase.class.getName());
|
threadPool = new TestThreadPool(AggregatorTestCase.class.getName());
|
||||||
threadPoolExecutor = (ThreadPoolExecutor) threadPool.executor(ThreadPool.Names.SEARCH_WORKER);
|
threadPoolExecutor = (ThreadPoolExecutor) threadPool.executor(ThreadPool.Names.SEARCH);
|
||||||
List<SearchPlugin> plugins = new ArrayList<>(getSearchPlugins());
|
List<SearchPlugin> plugins = new ArrayList<>(getSearchPlugins());
|
||||||
plugins.add(new AggCardinalityUpperBoundPlugin());
|
plugins.add(new AggCardinalityUpperBoundPlugin());
|
||||||
SearchModule searchModule = new SearchModule(Settings.EMPTY, plugins);
|
SearchModule searchModule = new SearchModule(Settings.EMPTY, plugins);
|
||||||
|
|
|
@ -9,33 +9,22 @@
|
||||||
|
|
||||||
package org.elasticsearch.search.internal;
|
package org.elasticsearch.search.internal;
|
||||||
|
|
||||||
import org.elasticsearch.core.TimeValue;
|
import org.elasticsearch.cluster.service.ClusterService;
|
||||||
import org.elasticsearch.index.IndexService;
|
|
||||||
import org.elasticsearch.index.shard.IndexShard;
|
|
||||||
import org.elasticsearch.indices.IndicesService;
|
|
||||||
import org.elasticsearch.search.SearchService;
|
import org.elasticsearch.search.SearchService;
|
||||||
import org.elasticsearch.test.ESSingleNodeTestCase;
|
import org.elasticsearch.test.ESSingleNodeTestCase;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class ConcurrentSearchSingleNodeTests extends ESSingleNodeTestCase {
|
public class ConcurrentSearchSingleNodeTests extends ESSingleNodeTestCase {
|
||||||
|
|
||||||
private final boolean concurrentSearch = randomBoolean();
|
private final boolean concurrentSearch = randomBoolean();
|
||||||
|
|
||||||
public void testConcurrentSearch() throws IOException {
|
public void testConcurrentSearch() {
|
||||||
client().admin().indices().prepareCreate("index").get();
|
client().admin().indices().prepareCreate("index").get();
|
||||||
IndicesService indicesService = getInstanceFromNode(IndicesService.class);
|
ClusterService clusterService = getInstanceFromNode(ClusterService.class);
|
||||||
IndexService indexService = indicesService.iterator().next();
|
int minDocsPerSlice = SearchService.MINIMUM_DOCS_PER_SLICE.get(clusterService.getSettings());
|
||||||
IndexShard shard = indexService.getShard(0);
|
if (concurrentSearch) {
|
||||||
SearchService searchService = getInstanceFromNode(SearchService.class);
|
assertEquals(1, minDocsPerSlice);
|
||||||
ShardSearchRequest shardSearchRequest = new ShardSearchRequest(shard.shardId(), 0L, AliasFilter.EMPTY);
|
} else {
|
||||||
try (SearchContext searchContext = searchService.createSearchContext(shardSearchRequest, TimeValue.MINUS_ONE)) {
|
assertEquals(50_000, minDocsPerSlice);
|
||||||
ContextIndexSearcher searcher = searchContext.searcher();
|
|
||||||
if (concurrentSearch) {
|
|
||||||
assertEquals(1, searcher.getMinimumDocsPerSlice());
|
|
||||||
} else {
|
|
||||||
assertEquals(50_000, searcher.getMinimumDocsPerSlice());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,34 +9,23 @@
|
||||||
|
|
||||||
package org.elasticsearch.search.internal;
|
package org.elasticsearch.search.internal;
|
||||||
|
|
||||||
import org.elasticsearch.core.TimeValue;
|
import org.elasticsearch.cluster.service.ClusterService;
|
||||||
import org.elasticsearch.index.IndexService;
|
|
||||||
import org.elasticsearch.index.shard.IndexShard;
|
|
||||||
import org.elasticsearch.indices.IndicesService;
|
|
||||||
import org.elasticsearch.search.SearchService;
|
import org.elasticsearch.search.SearchService;
|
||||||
import org.elasticsearch.test.ESIntegTestCase;
|
import org.elasticsearch.test.ESIntegTestCase;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST, numDataNodes = 1)
|
@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST, numDataNodes = 1)
|
||||||
public class ConcurrentSearchTestPluginTests extends ESIntegTestCase {
|
public class ConcurrentSearchTestPluginTests extends ESIntegTestCase {
|
||||||
|
|
||||||
private final boolean concurrentSearch = randomBoolean();
|
private final boolean concurrentSearch = randomBoolean();
|
||||||
|
|
||||||
public void testConcurrentSearch() throws IOException {
|
public void testConcurrentSearch() {
|
||||||
client().admin().indices().prepareCreate("index").get();
|
client().admin().indices().prepareCreate("index").get();
|
||||||
IndicesService indicesService = internalCluster().getDataNodeInstance(IndicesService.class);
|
ClusterService clusterService = internalCluster().getDataNodeInstance(ClusterService.class);
|
||||||
IndexService indexService = indicesService.iterator().next();
|
int minDocsPerSlice = SearchService.MINIMUM_DOCS_PER_SLICE.get(clusterService.getSettings());
|
||||||
IndexShard shard = indexService.getShard(0);
|
if (concurrentSearch) {
|
||||||
SearchService searchService = internalCluster().getDataNodeInstance(SearchService.class);
|
assertEquals(1, minDocsPerSlice);
|
||||||
ShardSearchRequest shardSearchRequest = new ShardSearchRequest(shard.shardId(), 0L, AliasFilter.EMPTY);
|
} else {
|
||||||
try (SearchContext searchContext = searchService.createSearchContext(shardSearchRequest, TimeValue.MINUS_ONE)) {
|
assertEquals(50_000, minDocsPerSlice);
|
||||||
ContextIndexSearcher searcher = searchContext.searcher();
|
|
||||||
if (concurrentSearch) {
|
|
||||||
assertEquals(1, searcher.getMinimumDocsPerSlice());
|
|
||||||
} else {
|
|
||||||
assertEquals(50_000, searcher.getMinimumDocsPerSlice());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ package org.elasticsearch.xpack.ccr.repository;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.apache.lucene.index.IndexFileNames;
|
||||||
import org.apache.lucene.store.IOContext;
|
import org.apache.lucene.store.IOContext;
|
||||||
import org.apache.lucene.store.IndexInput;
|
import org.apache.lucene.store.IndexInput;
|
||||||
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
||||||
|
@ -244,9 +245,10 @@ public class CcrRestoreSourceService extends AbstractLifecycleComponent implemen
|
||||||
|
|
||||||
private long readFileBytes(String fileName, ByteArray reference) throws IOException {
|
private long readFileBytes(String fileName, ByteArray reference) throws IOException {
|
||||||
try (Releasable ignored = keyedLock.acquire(fileName)) {
|
try (Releasable ignored = keyedLock.acquire(fileName)) {
|
||||||
|
var context = fileName.startsWith(IndexFileNames.SEGMENTS) ? IOContext.READONCE : IOContext.READ;
|
||||||
final IndexInput indexInput = cachedInputs.computeIfAbsent(fileName, f -> {
|
final IndexInput indexInput = cachedInputs.computeIfAbsent(fileName, f -> {
|
||||||
try {
|
try {
|
||||||
return commitRef.getIndexCommit().getDirectory().openInput(fileName, IOContext.READONCE);
|
return commitRef.getIndexCommit().getDirectory().openInput(fileName, context);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new UncheckedIOException(e);
|
throw new UncheckedIOException(e);
|
||||||
}
|
}
|
||||||
|
@ -256,7 +258,7 @@ public class CcrRestoreSourceService extends AbstractLifecycleComponent implemen
|
||||||
|
|
||||||
long offsetAfterRead = indexInput.getFilePointer();
|
long offsetAfterRead = indexInput.getFilePointer();
|
||||||
|
|
||||||
if (offsetAfterRead == indexInput.length()) {
|
if (offsetAfterRead == indexInput.length() || context == IOContext.READONCE) {
|
||||||
cachedInputs.remove(fileName);
|
cachedInputs.remove(fileName);
|
||||||
IOUtils.close(indexInput);
|
IOUtils.close(indexInput);
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,7 +196,7 @@ public class OldSegmentInfos implements Cloneable, Iterable<SegmentCommitInfo> {
|
||||||
|
|
||||||
long generation = generationFromSegmentsFileName(segmentFileName);
|
long generation = generationFromSegmentsFileName(segmentFileName);
|
||||||
// System.out.println(Thread.currentThread() + ": SegmentInfos.readCommit " + segmentFileName);
|
// System.out.println(Thread.currentThread() + ": SegmentInfos.readCommit " + segmentFileName);
|
||||||
try (ChecksumIndexInput input = directory.openChecksumInput(segmentFileName, IOContext.READ)) {
|
try (ChecksumIndexInput input = directory.openChecksumInput(segmentFileName, IOContext.READONCE)) {
|
||||||
try {
|
try {
|
||||||
return readCommit(directory, input, generation, minSupportedMajorVersion);
|
return readCommit(directory, input, generation, minSupportedMajorVersion);
|
||||||
} catch (EOFException | NoSuchFileException | FileNotFoundException e) {
|
} catch (EOFException | NoSuchFileException | FileNotFoundException e) {
|
||||||
|
|
|
@ -221,7 +221,6 @@ public abstract class MetadataCachingIndexInput extends BlobCacheBufferedIndexIn
|
||||||
ThreadPool.Names.SNAPSHOT,
|
ThreadPool.Names.SNAPSHOT,
|
||||||
ThreadPool.Names.GENERIC,
|
ThreadPool.Names.GENERIC,
|
||||||
ThreadPool.Names.SEARCH,
|
ThreadPool.Names.SEARCH,
|
||||||
ThreadPool.Names.SEARCH_WORKER,
|
|
||||||
ThreadPool.Names.SEARCH_THROTTLED,
|
ThreadPool.Names.SEARCH_THROTTLED,
|
||||||
|
|
||||||
// Cache asynchronous fetching runs on a dedicated thread pool.
|
// Cache asynchronous fetching runs on a dedicated thread pool.
|
||||||
|
|
|
@ -692,7 +692,7 @@ public class SearchableSnapshotDirectoryTests extends AbstractSearchableSnapshot
|
||||||
private void testIndexInputs(final CheckedBiConsumer<IndexInput, IndexInput, Exception> consumer) throws Exception {
|
private void testIndexInputs(final CheckedBiConsumer<IndexInput, IndexInput, Exception> consumer) throws Exception {
|
||||||
testDirectories((directory, snapshotDirectory) -> {
|
testDirectories((directory, snapshotDirectory) -> {
|
||||||
for (String fileName : randomSubsetOf(Arrays.asList(snapshotDirectory.listAll()))) {
|
for (String fileName : randomSubsetOf(Arrays.asList(snapshotDirectory.listAll()))) {
|
||||||
final IOContext context = randomIOContext();
|
final IOContext context = fileName.startsWith(IndexFileNames.SEGMENTS) ? IOContext.READONCE : randomIOContext();
|
||||||
try (IndexInput indexInput = directory.openInput(fileName, context)) {
|
try (IndexInput indexInput = directory.openInput(fileName, context)) {
|
||||||
final List<Closeable> closeables = new ArrayList<>();
|
final List<Closeable> closeables = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -29,7 +29,7 @@ subprojects {
|
||||||
|
|
||||||
restResources {
|
restResources {
|
||||||
restApi {
|
restApi {
|
||||||
include '_common', 'bulk', 'count', 'cluster', 'index', 'indices', 'field_caps', 'msearch',
|
include 'capabilities', '_common', 'bulk', 'count', 'cluster', 'index', 'indices', 'field_caps', 'msearch',
|
||||||
'search', 'async_search', 'graph', '*_point_in_time', 'put_script', 'scripts_painless_execute'
|
'search', 'async_search', 'graph', '*_point_in_time', 'put_script', 'scripts_painless_execute'
|
||||||
}
|
}
|
||||||
restTests {
|
restTests {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue