1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
<?php
/**
* Placeholder for the engine class. Keep this abstract until E7/E8 land so
* it is not auto-discovered as a selectable backend before it can operate.
*/
abstract class VyOSElasticModernFulltextStorageEngine
extends PhabricatorFulltextStorageEngine {
private $version = null;
public function setVersion($version) {
$version = (int)$version;
if ($version < 7) {
throw new Exception(
pht(
'Unsupported Elasticsearch version "%d" for the '.
'"elasticsearch-modern" engine. This engine supports version 7 '.
'and above (Elasticsearch 7.x, 8.x, or OpenSearch 1.x/2.x/3.x). '.
'For ES 5.x, use the bundled "elasticsearch" engine instead.',
$version));
}
$this->version = $version;
return $this;
}
public function getVersion() {
if ($this->version === null) {
throw new Exception(
pht('Version not configured; call setVersion() or setService() first.'));
}
return $this->version;
}
public function getDocumentUri($type, $phid) {
return '/_doc/'.$phid;
}
public function getSearchUri(array $types) {
return '/_search';
}
public function buildTypeFilter(array $types) {
return array(
'terms' => array(
'documentType' => array_values($types),
),
);
}
public function buildIndexMappings(
array $doc_types, array $fields, array $relationships, $text_type) {
// These are emitted as fixed standard fields at the end of the mapping.
// Caller-supplied $fields or $relationships must not shadow them.
static $reserved = array('documentType', 'dateCreated', 'lastModified');
$rel_ts_keys = array_map(function($r) { return $r.'_ts'; }, $relationships);
$all_caller_keys = array_merge($fields, $relationships, $rel_ts_keys);
// Check for caller-supplied names that shadow reserved fields.
$collisions = array_intersect($all_caller_keys, $reserved);
if ($collisions) {
throw new Exception(
pht(
'buildIndexMappings(): caller-supplied field(s) "%s" collide with '.
'reserved mapping keys.',
implode('", "', array_values($collisions))));
}
// Check for duplicates within caller-supplied keys themselves
// (e.g. a field named "foo_ts" that would clash with relationship "foo"'s
// implicit timestamp slot).
$counts = array_count_values($all_caller_keys);
$duplicates = array_keys(array_filter($counts, function($c) { return $c > 1; }));
if ($duplicates) {
throw new Exception(
pht(
'buildIndexMappings(): caller-supplied key(s) "%s" appear more '.
'than once (check for field/relationship/timestamp-slot collisions).',
implode('", "', $duplicates)));
}
$properties = array();
foreach ($fields as $field) {
$properties[$field] = array(
'type' => $text_type,
'fields' => array(
'raw' => array(
'type' => $text_type,
'analyzer' => 'english_exact',
'search_analyzer' => 'english',
'search_quote_analyzer' => 'english_exact',
),
'keywords' => array(
'type' => $text_type,
'analyzer' => 'letter_stop',
),
'stems' => array(
'type' => $text_type,
'analyzer' => 'english_stem',
),
),
);
}
foreach ($relationships as $rel) {
$properties[$rel] = array(
'type' => 'keyword',
'doc_values' => false,
);
$properties[$rel.'_ts'] = array(
'type' => 'date',
);
}
$properties['documentType'] = array('type' => 'keyword');
$properties['dateCreated'] = array('type' => 'date');
$properties['lastModified'] = array('type' => 'date');
// The $doc_types parameter is part of the signature for symmetry
// with the bundled engine's per-type loop, but the typeless API
// emits one mapping shared across all doc types.
return array('properties' => $properties);
}
public function getEngineIdentifier() {
return 'elasticsearch-modern';
}
public function getHostType() {
return new VyOSElasticModernHost($this);
}
public function reindexAbstractDocument(
PhabricatorSearchAbstractDocument $doc) {
throw new Exception(pht(
'reindexAbstractDocument() is not yet implemented on '.
'VyOSElasticModernFulltextStorageEngine; lands in Task E7.'));
}
public function executeSearch(PhabricatorSavedQuery $query) {
throw new Exception(pht(
'executeSearch() is not yet implemented; lands in Task E8.'));
}
public function indexExists() {
throw new Exception(pht(
'indexExists() is not yet implemented; lands in Task E8.'));
}
public function getIndexStats() {
throw new Exception(pht(
'getIndexStats() is not yet implemented; lands in Task E8.'));
}
}
|