Skip to content

Commit 3e06af3

Browse files
JeroenDeDauwclaude
andcommitted
Support external-id and edtf property types for faceted search
Fixes #276 Both external-id and edtf properties use StringValue internally, so the DataValueTranslator already handles their values. The missing piece was that these datatype IDs were not included in the match statements of SearchIndexFieldsBuilder and ListFacetQueryBuilder, causing their facets to be silently ignored. With this change, both types are indexed as keywords and supported for list facets. Range facets for edtf are not yet supported, as that would require converting EDTF strings to dates at index time. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3e2ef0c commit 3e06af3

4 files changed

Lines changed: 78 additions & 4 deletions

File tree

src/Persistence/Search/Query/ListFacetQueryBuilder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public function buildQuery( FacetConfig $config, PropertyConstraints $constraint
3636
}
3737

3838
return match ( $this->dataTypeLookup->getDataTypeIdForProperty( $config->propertyId ) ) {
39-
'string' => $this->buildStringQuery( $name, $values ),
39+
'string', 'external-id', 'edtf' => $this->buildStringQuery( $name, $values ),
4040
'wikibase-item' => $this->buildStringQuery( $name, $values ),
4141
'quantity' => $this->buildQuantityQuery( $name, $values ),
4242
'time' => $this->buildTimeQuery( $name, $values ),

src/Persistence/Search/SearchIndexFieldsBuilder.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ private function getFieldTypeForPropertyId( PropertyId $propertyId ): ?string {
5353
private function getFieldTypeForDataTypeId( string $dataTypeId ): ?string {
5454
return match ( $dataTypeId ) {
5555
'quantity' => SearchIndexField::INDEX_TYPE_NUMBER,
56-
'string' => SearchIndexField::INDEX_TYPE_KEYWORD,
56+
'string', 'external-id', 'edtf' => SearchIndexField::INDEX_TYPE_KEYWORD,
5757
'time' => SearchIndexField::INDEX_TYPE_DATETIME,
5858
'wikibase-item' => SearchIndexField::INDEX_TYPE_KEYWORD,
5959
default => null

tests/phpunit/Persistence/Search/Query/ListFacetQueryBuilderTest.php

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class ListFacetQueryBuilderTest extends TestCase {
2525
private const STRING_PROPERTY = 'P200';
2626
private const TIME_PROPERTY = 'P300';
2727
private const ITEM_PROPERTY = 'P400';
28+
private const EXTERNAL_ID_PROPERTY = 'P500';
29+
private const EDTF_PROPERTY = 'P600';
2830

2931
public function testBuildsQueryForStringList(): void {
3032
$query = $this->newFacetQueryBuilder()->buildQuery(
@@ -55,7 +57,9 @@ private function newDataTypeLookup(): InMemoryDataTypeLookup {
5557
self::QUANTITY_PROPERTY => 'quantity',
5658
self::STRING_PROPERTY => 'string',
5759
self::TIME_PROPERTY => 'time',
58-
self::ITEM_PROPERTY => 'wikibase-item'
60+
self::ITEM_PROPERTY => 'wikibase-item',
61+
self::EXTERNAL_ID_PROPERTY => 'external-id',
62+
self::EDTF_PROPERTY => 'edtf'
5963
];
6064

6165
foreach ( $types as $pId => $type ) {
@@ -169,6 +173,38 @@ public function testBuildsAnyValueQuery(): void {
169173
);
170174
}
171175

176+
public function testBuildsQueryForExternalIdList(): void {
177+
$query = $this->newFacetQueryBuilder()->buildQuery(
178+
$this->newListFacetConfig( self::EXTERNAL_ID_PROPERTY ),
179+
new PropertyConstraints(
180+
new NumericPropertyId( self::EXTERNAL_ID_PROPERTY ),
181+
orSelectedValues: [ 'ID-001', 'ID-002' ]
182+
)
183+
);
184+
185+
$this->assertIsTermsQueryWithParams(
186+
self::EXTERNAL_ID_PROPERTY,
187+
[ 'ID-001', 'ID-002' ],
188+
$query
189+
);
190+
}
191+
192+
public function testBuildsQueryForEdtfList(): void {
193+
$query = $this->newFacetQueryBuilder()->buildQuery(
194+
$this->newListFacetConfig( self::EDTF_PROPERTY ),
195+
new PropertyConstraints(
196+
new NumericPropertyId( self::EDTF_PROPERTY ),
197+
orSelectedValues: [ '1850', '1920-03-15' ]
198+
)
199+
);
200+
201+
$this->assertIsTermsQueryWithParams(
202+
self::EDTF_PROPERTY,
203+
[ '1850', '1920-03-15' ],
204+
$query
205+
);
206+
}
207+
172208
public function testBuildsNullQueryWhenListIsEmpty(): void {
173209
$query = $this->newFacetQueryBuilder()->buildQuery(
174210
$this->newListFacetConfig( self::STRING_PROPERTY ),

tests/phpunit/Persistence/Search/SearchIndexFieldsBuilderTest.php

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ private function newDataTypeLookup(): InMemoryDataTypeLookup {
6666
'P100' => 'quantity',
6767
'P200' => 'string',
6868
'P300' => 'time',
69-
'P400' => 'wikibase-item'
69+
'P400' => 'wikibase-item',
70+
'P500' => 'external-id',
71+
'P600' => 'edtf'
7072
];
7173

7274
foreach ( $types as $pId => $type ) {
@@ -132,6 +134,42 @@ private function newProperty( string $id, string $dataType ): Property {
132134
return new Property( new NumericPropertyId( $id ), null, $dataType );
133135
}
134136

137+
public function testCreatesKeywordFieldForExternalIdProperty(): void {
138+
$builder = $this->newBuilder(
139+
new Config(
140+
itemTypeProperty: new NumericPropertyId( 'P1' ),
141+
facets: new FacetConfigList(
142+
$this->newFacetConfig( 'Q1', 'P500' )
143+
)
144+
)
145+
);
146+
147+
$fields = $builder->createFieldObjects();
148+
149+
$this->assertEquals(
150+
new AggregatableKeywordIndexField( 'wbfs_P500', SearchIndexField::INDEX_TYPE_KEYWORD, $this->cirrusSearch->getConfig() ),
151+
$fields['wbfs_P500']
152+
);
153+
}
154+
155+
public function testCreatesKeywordFieldForEdtfProperty(): void {
156+
$builder = $this->newBuilder(
157+
new Config(
158+
itemTypeProperty: new NumericPropertyId( 'P1' ),
159+
facets: new FacetConfigList(
160+
$this->newFacetConfig( 'Q1', 'P600' )
161+
)
162+
)
163+
);
164+
165+
$fields = $builder->createFieldObjects();
166+
167+
$this->assertEquals(
168+
new AggregatableKeywordIndexField( 'wbfs_P600', SearchIndexField::INDEX_TYPE_KEYWORD, $this->cirrusSearch->getConfig() ),
169+
$fields['wbfs_P600']
170+
);
171+
}
172+
135173
public function testDoesNotReturnFieldsForMissingProperties(): void {
136174
$builder = $this->newBuilder(
137175
new Config(

0 commit comments

Comments
 (0)