19
19
20
20
package org .elasticsearch .index .query ;
21
21
22
+ import org .apache .lucene .index .IndexOptions ;
22
23
import org .apache .lucene .search .intervals .FilteredIntervalsSource ;
23
24
import org .apache .lucene .search .intervals .IntervalIterator ;
24
25
import org .apache .lucene .search .intervals .Intervals ;
25
26
import org .apache .lucene .search .intervals .IntervalsSource ;
27
+ import org .apache .lucene .util .BytesRef ;
26
28
import org .elasticsearch .Version ;
27
29
import org .elasticsearch .common .ParseField ;
28
30
import org .elasticsearch .common .ParsingException ;
@@ -80,6 +82,8 @@ public static IntervalsSourceProvider fromXContent(XContentParser parser) throws
80
82
return Combine .fromXContent (parser );
81
83
case "prefix" :
82
84
return Prefix .fromXContent (parser );
85
+ case "wildcard" :
86
+ return Wildcard .fromXContent (parser );
83
87
}
84
88
throw new ParsingException (parser .getTokenLocation (),
85
89
"Unknown interval type [" + parser .currentName () + "], expecting one of [match, any_of, all_of, prefix]" );
@@ -446,18 +450,18 @@ public static class Prefix extends IntervalsSourceProvider {
446
450
447
451
public static final String NAME = "prefix" ;
448
452
449
- private final String term ;
453
+ private final String prefix ;
450
454
private final String analyzer ;
451
455
private final String useField ;
452
456
453
- public Prefix (String term , String analyzer , String useField ) {
454
- this .term = term ;
457
+ public Prefix (String prefix , String analyzer , String useField ) {
458
+ this .prefix = prefix ;
455
459
this .analyzer = analyzer ;
456
460
this .useField = useField ;
457
461
}
458
462
459
463
public Prefix (StreamInput in ) throws IOException {
460
- this .term = in .readString ();
464
+ this .prefix = in .readString ();
461
465
this .analyzer = in .readOptionalString ();
462
466
this .useField = in .readOptionalString ();
463
467
}
@@ -472,10 +476,10 @@ public IntervalsSource getSource(QueryShardContext context, MappedFieldType fiel
472
476
if (useField != null ) {
473
477
fieldType = context .fieldMapper (useField );
474
478
assert fieldType != null ;
475
- source = Intervals .fixField (useField , fieldType .intervals (term , 0 , false , analyzer , true ));
479
+ source = Intervals .fixField (useField , fieldType .intervals (prefix , 0 , false , analyzer , true ));
476
480
}
477
481
else {
478
- source = fieldType .intervals (term , 0 , false , analyzer , true );
482
+ source = fieldType .intervals (prefix , 0 , false , analyzer , true );
479
483
}
480
484
return source ;
481
485
}
@@ -492,14 +496,14 @@ public boolean equals(Object o) {
492
496
if (this == o ) return true ;
493
497
if (o == null || getClass () != o .getClass ()) return false ;
494
498
Prefix prefix = (Prefix ) o ;
495
- return Objects .equals (term , prefix .term ) &&
499
+ return Objects .equals (this . prefix , prefix .prefix ) &&
496
500
Objects .equals (analyzer , prefix .analyzer ) &&
497
501
Objects .equals (useField , prefix .useField );
498
502
}
499
503
500
504
@ Override
501
505
public int hashCode () {
502
- return Objects .hash (term , analyzer , useField );
506
+ return Objects .hash (prefix , analyzer , useField );
503
507
}
504
508
505
509
@ Override
@@ -509,15 +513,15 @@ public String getWriteableName() {
509
513
510
514
@ Override
511
515
public void writeTo (StreamOutput out ) throws IOException {
512
- out .writeString (term );
516
+ out .writeString (prefix );
513
517
out .writeOptionalString (analyzer );
514
518
out .writeOptionalString (useField );
515
519
}
516
520
517
521
@ Override
518
522
public XContentBuilder toXContent (XContentBuilder builder , Params params ) throws IOException {
519
523
builder .startObject (NAME );
520
- builder .field ("term " , term );
524
+ builder .field ("prefix " , prefix );
521
525
if (analyzer != null ) {
522
526
builder .field ("analyzer" , analyzer );
523
527
}
@@ -535,7 +539,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
535
539
return new Prefix (term , analyzer , useField );
536
540
});
537
541
static {
538
- PARSER .declareString (constructorArg (), new ParseField ("term " ));
542
+ PARSER .declareString (constructorArg (), new ParseField ("prefix " ));
539
543
PARSER .declareString (optionalConstructorArg (), new ParseField ("analyzer" ));
540
544
PARSER .declareString (optionalConstructorArg (), new ParseField ("use_field" ));
541
545
}
@@ -545,6 +549,123 @@ public static Prefix fromXContent(XContentParser parser) throws IOException {
545
549
}
546
550
}
547
551
552
+ public static class Wildcard extends IntervalsSourceProvider {
553
+
554
+ public static final String NAME = "wildcard" ;
555
+
556
+ private final String pattern ;
557
+ private final String analyzer ;
558
+ private final String useField ;
559
+
560
+ public Wildcard (String pattern , String analyzer , String useField ) {
561
+ this .pattern = pattern ;
562
+ this .analyzer = analyzer ;
563
+ this .useField = useField ;
564
+ }
565
+
566
+ public Wildcard (StreamInput in ) throws IOException {
567
+ this .pattern = in .readString ();
568
+ this .analyzer = in .readOptionalString ();
569
+ this .useField = in .readOptionalString ();
570
+ }
571
+
572
+ @ Override
573
+ public IntervalsSource getSource (QueryShardContext context , MappedFieldType fieldType ) {
574
+ NamedAnalyzer analyzer = fieldType .searchAnalyzer ();
575
+ if (this .analyzer != null ) {
576
+ analyzer = context .getMapperService ().getIndexAnalyzers ().get (this .analyzer );
577
+ }
578
+ IntervalsSource source ;
579
+ if (useField != null ) {
580
+ fieldType = context .fieldMapper (useField );
581
+ assert fieldType != null ;
582
+ checkPositions (fieldType );
583
+ if (this .analyzer == null ) {
584
+ analyzer = fieldType .searchAnalyzer ();
585
+ }
586
+ BytesRef normalizedTerm = analyzer .normalize (useField , pattern );
587
+ // TODO Intervals.wildcard() should take BytesRef
588
+ source = Intervals .fixField (useField , Intervals .wildcard (normalizedTerm .utf8ToString ()));
589
+ }
590
+ else {
591
+ checkPositions (fieldType );
592
+ BytesRef normalizedTerm = analyzer .normalize (fieldType .name (), pattern );
593
+ source = Intervals .wildcard (normalizedTerm .utf8ToString ());
594
+ }
595
+ return source ;
596
+ }
597
+
598
+ private void checkPositions (MappedFieldType type ) {
599
+ if (type .indexOptions ().compareTo (IndexOptions .DOCS_AND_FREQS_AND_POSITIONS ) < 0 ) {
600
+ throw new IllegalArgumentException ("Cannot create intervals over field [" + type .name () + "] with no positions indexed" );
601
+ }
602
+ }
603
+
604
+ @ Override
605
+ public void extractFields (Set <String > fields ) {
606
+ if (useField != null ) {
607
+ fields .add (useField );
608
+ }
609
+ }
610
+
611
+ @ Override
612
+ public boolean equals (Object o ) {
613
+ if (this == o ) return true ;
614
+ if (o == null || getClass () != o .getClass ()) return false ;
615
+ Prefix prefix = (Prefix ) o ;
616
+ return Objects .equals (pattern , prefix .prefix ) &&
617
+ Objects .equals (analyzer , prefix .analyzer ) &&
618
+ Objects .equals (useField , prefix .useField );
619
+ }
620
+
621
+ @ Override
622
+ public int hashCode () {
623
+ return Objects .hash (pattern , analyzer , useField );
624
+ }
625
+
626
+ @ Override
627
+ public String getWriteableName () {
628
+ return NAME ;
629
+ }
630
+
631
+ @ Override
632
+ public void writeTo (StreamOutput out ) throws IOException {
633
+ out .writeString (pattern );
634
+ out .writeOptionalString (analyzer );
635
+ out .writeOptionalString (useField );
636
+ }
637
+
638
+ @ Override
639
+ public XContentBuilder toXContent (XContentBuilder builder , Params params ) throws IOException {
640
+ builder .startObject (NAME );
641
+ builder .field ("pattern" , pattern );
642
+ if (analyzer != null ) {
643
+ builder .field ("analyzer" , analyzer );
644
+ }
645
+ if (useField != null ) {
646
+ builder .field ("use_field" , useField );
647
+ }
648
+ builder .endObject ();
649
+ return builder ;
650
+ }
651
+
652
+ private static final ConstructingObjectParser <Wildcard , Void > PARSER = new ConstructingObjectParser <>(NAME , args -> {
653
+ String term = (String ) args [0 ];
654
+ String analyzer = (String ) args [1 ];
655
+ String useField = (String ) args [2 ];
656
+ return new Wildcard (term , analyzer , useField );
657
+ });
658
+ static {
659
+ PARSER .declareString (constructorArg (), new ParseField ("pattern" ));
660
+ PARSER .declareString (optionalConstructorArg (), new ParseField ("analyzer" ));
661
+ PARSER .declareString (optionalConstructorArg (), new ParseField ("use_field" ));
662
+ }
663
+
664
+ public static Wildcard fromXContent (XContentParser parser ) throws IOException {
665
+ return PARSER .parse (parser , null );
666
+ }
667
+ }
668
+
548
669
static class ScriptFilterSource extends FilteredIntervalsSource {
549
670
550
671
final IntervalFilterScript script ;
0 commit comments