|
9 | 9 | package org.opensearch.index.mapper;
|
10 | 10 |
|
11 | 11 | import org.apache.lucene.document.FieldType;
|
| 12 | +import org.apache.lucene.document.SortedSetDocValuesField; |
12 | 13 | import org.apache.lucene.index.IndexOptions;
|
13 | 14 | import org.apache.lucene.index.Term;
|
14 | 15 | import org.apache.lucene.search.FieldExistsQuery;
|
|
24 | 25 | import org.apache.lucene.search.WildcardQuery;
|
25 | 26 | import org.apache.lucene.util.BytesRef;
|
26 | 27 | import org.apache.lucene.util.automaton.Operations;
|
| 28 | +import org.opensearch.common.lucene.search.AutomatonQueries; |
27 | 29 | import org.opensearch.common.unit.Fuzziness;
|
28 | 30 | import org.opensearch.index.analysis.AnalyzerScope;
|
29 | 31 | import org.opensearch.index.analysis.NamedAnalyzer;
|
@@ -138,47 +140,284 @@ public void testRewriteValue() {
|
138 | 140 | assertEquals("field.bar=foo", searchValuesDocPath);
|
139 | 141 | }
|
140 | 142 |
|
141 |
| - public void testTermQuery() { |
| 143 | + public void testTermQueryCaseInsensitive() { |
142 | 144 |
|
143 |
| - FlatObjectFieldMapper.FlatObjectFieldType flatParentFieldType = (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType( |
| 145 | + // 1.test isSearchable=true, hasDocValues=true, mappedFieldTypeName=null |
| 146 | + { |
| 147 | + FlatObjectFieldMapper.FlatObjectFieldType flatParentFieldType = |
| 148 | + (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType("field", null, true, true); |
| 149 | + |
| 150 | + MappedFieldType dynamicMappedFieldType = new FlatObjectFieldMapper.FlatObjectFieldType( |
| 151 | + "field.bar", |
| 152 | + flatParentFieldType.name(), |
| 153 | + flatParentFieldType.getValueFieldType(), |
| 154 | + flatParentFieldType.getValueAndPathFieldType() |
| 155 | + ); |
| 156 | + assertEquals( |
| 157 | + AutomatonQueries.caseInsensitiveTermQuery(new Term("field._valueAndPath", "field.bar=fOo")), |
| 158 | + dynamicMappedFieldType.termQueryCaseInsensitive("fOo", null) |
| 159 | + ); |
| 160 | + } |
| 161 | + |
| 162 | + // 2.test isSearchable=true, hasDocValues=false, mappedFieldTypeName=null |
| 163 | + { |
| 164 | + FlatObjectFieldMapper.FlatObjectFieldType ft = (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType( |
| 165 | + "field", |
| 166 | + null, |
| 167 | + true, |
| 168 | + false |
| 169 | + ); |
| 170 | + assertEquals( |
| 171 | + AutomatonQueries.caseInsensitiveTermQuery(new Term("field._value", "fOo")), |
| 172 | + ft.termQueryCaseInsensitive("fOo", null) |
| 173 | + ); |
| 174 | + } |
| 175 | + |
| 176 | + // test isSearchable=true, hasDocValues=false, mappedFieldTypeName!=null |
| 177 | + { |
| 178 | + FlatObjectFieldMapper.FlatObjectFieldType ft = (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType( |
| 179 | + "field", |
| 180 | + "field", |
| 181 | + true, |
| 182 | + false |
| 183 | + ); |
| 184 | + Query expected = new TermQuery(new Term("field" + VALUE_AND_PATH_SUFFIX, new BytesRef("fOo"))); |
| 185 | + |
| 186 | + assertEquals(expected, ft.termQuery("fOo", MOCK_QSC_ENABLE_INDEX_DOC_VALUES)); |
| 187 | + } |
| 188 | + |
| 189 | + // 3.test isSearchable=false, hasDocValues=true, mappedFieldTypeName=null |
| 190 | + { |
| 191 | + FlatObjectFieldMapper.FlatObjectFieldType ft = (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType( |
| 192 | + "field", |
| 193 | + null, |
| 194 | + false, |
| 195 | + true |
| 196 | + ); |
| 197 | + Query expected = AutomatonQueries.createAutomatonQuery( |
| 198 | + new Term("field" + VALUE_SUFFIX, "field.fOo"), |
| 199 | + AutomatonQueries.toCaseInsensitiveString("field.fOo", Integer.MAX_VALUE), |
| 200 | + MultiTermQuery.DOC_VALUES_REWRITE |
| 201 | + ); |
| 202 | + assertEquals(expected, ft.termQueryCaseInsensitive("fOo", MOCK_QSC_ENABLE_INDEX_DOC_VALUES)); |
| 203 | + } |
| 204 | + |
| 205 | + // test isSearchable=false, hasDocValues=true, mappedFieldTypeName!=null |
| 206 | + { |
| 207 | + FlatObjectFieldMapper.FlatObjectFieldType ft = (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType( |
| 208 | + "field", |
| 209 | + "field", |
| 210 | + false, |
| 211 | + true |
| 212 | + ); |
| 213 | + Query expected = AutomatonQueries.createAutomatonQuery( |
| 214 | + new Term("field" + VALUE_AND_PATH_SUFFIX, "field.fOo"), |
| 215 | + AutomatonQueries.toCaseInsensitiveString("field.fOo", Integer.MAX_VALUE), |
| 216 | + MultiTermQuery.DOC_VALUES_REWRITE |
| 217 | + ); |
| 218 | + |
| 219 | + assertEquals(expected, ft.termQueryCaseInsensitive("fOo", MOCK_QSC_ENABLE_INDEX_DOC_VALUES)); |
| 220 | + } |
| 221 | + |
| 222 | + // 4.test isSearchable=false, hasDocValues=false, mappedFieldTypeName=null |
| 223 | + { |
| 224 | + FlatObjectFieldMapper.FlatObjectFieldType ft = (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType( |
| 225 | + "field", |
| 226 | + null, |
| 227 | + false, |
| 228 | + false |
| 229 | + ); |
| 230 | + IllegalArgumentException e = expectThrows( |
| 231 | + IllegalArgumentException.class, |
| 232 | + () -> ft.termQueryCaseInsensitive("foo", MOCK_QSC_ENABLE_INDEX_DOC_VALUES) |
| 233 | + ); |
| 234 | + assertEquals( |
| 235 | + "Cannot search on field [field._value] since it is both not indexed, and does not have doc_values " + "enabled.", |
| 236 | + e.getMessage() |
| 237 | + ); |
| 238 | + } |
| 239 | + |
| 240 | + // test isSearchable=false, hasDocValues=false, mappedFieldTypeName!=null |
| 241 | + { |
| 242 | + FlatObjectFieldMapper.FlatObjectFieldType ft = (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType( |
| 243 | + "field", |
| 244 | + "field", |
| 245 | + false, |
| 246 | + false |
| 247 | + ); |
| 248 | + IllegalArgumentException e = expectThrows( |
| 249 | + IllegalArgumentException.class, |
| 250 | + () -> ft.termQuery("foo", MOCK_QSC_ENABLE_INDEX_DOC_VALUES) |
| 251 | + ); |
| 252 | + assertEquals( |
| 253 | + "Cannot search on field [field._valueAndPath] since it is both not indexed, and does not have doc_values " + "enabled.", |
| 254 | + e.getMessage() |
| 255 | + ); |
| 256 | + } |
| 257 | + |
| 258 | + MappedFieldType unsearchable = new FlatObjectFieldMapper.FlatObjectFieldType( |
144 | 259 | "field",
|
145 | 260 | null,
|
146 |
| - true, |
147 |
| - true |
| 261 | + false, |
| 262 | + false, |
| 263 | + null, |
| 264 | + Collections.emptyMap() |
| 265 | + ); |
| 266 | + IllegalArgumentException e = expectThrows( |
| 267 | + IllegalArgumentException.class, |
| 268 | + () -> unsearchable.termQuery("bar", MOCK_QSC_ENABLE_INDEX_DOC_VALUES) |
148 | 269 | );
|
| 270 | + assertEquals( |
| 271 | + "Cannot search on field [field._value] since it is both not indexed, and does not have doc_values enabled.", |
| 272 | + e.getMessage() |
| 273 | + ); |
| 274 | + } |
149 | 275 |
|
150 |
| - // when searching for "foo" in "field", the term query is directed to search "foo" in field._value field |
151 |
| - String searchFieldName = (flatParentFieldType).directSubfield(); |
152 |
| - String searchValues = (flatParentFieldType).rewriteValue("foo"); |
153 |
| - assertEquals("foo", searchValues); |
154 |
| - assertEquals(new TermQuery(new Term(searchFieldName, searchValues)), flatParentFieldType.termQuery(searchValues, null)); |
| 276 | + public void testTermQuery() { |
155 | 277 |
|
156 |
| - MappedFieldType dynamicMappedFieldType = new FlatObjectFieldMapper.FlatObjectFieldType( |
157 |
| - "field.bar", |
158 |
| - flatParentFieldType.name(), |
159 |
| - flatParentFieldType.getValueFieldType(), |
160 |
| - flatParentFieldType.getValueAndPathFieldType() |
161 |
| - ); |
| 278 | + // 1.test isSearchable=true, hasDocValues=true, mappedFieldTypeName=null |
| 279 | + { |
| 280 | + FlatObjectFieldMapper.FlatObjectFieldType flatParentFieldType = |
| 281 | + (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType("field", null, true, true); |
162 | 282 |
|
163 |
| - // when searching for "foo" in "field.bar", the term query is directed to search in field._valueAndPath field |
164 |
| - String searchFieldNameDocPath = ((FlatObjectFieldMapper.FlatObjectFieldType) dynamicMappedFieldType).directSubfield(); |
165 |
| - String searchValuesDocPath = ((FlatObjectFieldMapper.FlatObjectFieldType) dynamicMappedFieldType).rewriteValue("foo"); |
166 |
| - assertEquals("field.bar=foo", searchValuesDocPath); |
167 |
| - assertEquals(new TermQuery(new Term(searchFieldNameDocPath, searchValuesDocPath)), dynamicMappedFieldType.termQuery("foo", null)); |
| 283 | + // when searching for "foo" in "field", the term query is directed to search "foo" in field._value field |
| 284 | + String searchFieldName = (flatParentFieldType).directSubfield(); |
| 285 | + String searchValues = (flatParentFieldType).rewriteValue("foo"); |
| 286 | + assertEquals("foo", searchValues); |
| 287 | + assertEquals(new TermQuery(new Term(searchFieldName, searchValues)), flatParentFieldType.termQuery(searchValues, null)); |
| 288 | + |
| 289 | + MappedFieldType dynamicMappedFieldType = new FlatObjectFieldMapper.FlatObjectFieldType( |
| 290 | + "field.bar", |
| 291 | + flatParentFieldType.name(), |
| 292 | + flatParentFieldType.getValueFieldType(), |
| 293 | + flatParentFieldType.getValueAndPathFieldType() |
| 294 | + ); |
| 295 | + |
| 296 | + // when searching for "foo" in "field.bar", the term query is directed to search in field._valueAndPath field |
| 297 | + String searchFieldNameDocPath = ((FlatObjectFieldMapper.FlatObjectFieldType) dynamicMappedFieldType).directSubfield(); |
| 298 | + String searchValuesDocPath = ((FlatObjectFieldMapper.FlatObjectFieldType) dynamicMappedFieldType).rewriteValue("foo"); |
| 299 | + assertEquals("field.bar=foo", searchValuesDocPath); |
| 300 | + assertEquals( |
| 301 | + new TermQuery(new Term(searchFieldNameDocPath, searchValuesDocPath)), |
| 302 | + dynamicMappedFieldType.termQuery("foo", null) |
| 303 | + ); |
| 304 | + |
| 305 | + } |
| 306 | + |
| 307 | + // 2.test isSearchable=true, hasDocValues=false, mappedFieldTypeName=null |
| 308 | + { |
| 309 | + FlatObjectFieldMapper.FlatObjectFieldType ft = (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType( |
| 310 | + "field", |
| 311 | + null, |
| 312 | + true, |
| 313 | + false |
| 314 | + ); |
| 315 | + Query expected = new TermQuery(new Term("field" + VALUE_SUFFIX, new BytesRef("foo"))); |
| 316 | + assertEquals(expected, ft.termQuery("foo", MOCK_QSC_ENABLE_INDEX_DOC_VALUES)); |
| 317 | + } |
| 318 | + |
| 319 | + // test isSearchable=true, hasDocValues=false, mappedFieldTypeName!=null |
| 320 | + { |
| 321 | + FlatObjectFieldMapper.FlatObjectFieldType ft = (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType( |
| 322 | + "field", |
| 323 | + "field", |
| 324 | + true, |
| 325 | + false |
| 326 | + ); |
| 327 | + Query expected = new TermQuery(new Term("field" + VALUE_AND_PATH_SUFFIX, new BytesRef("foo"))); |
| 328 | + |
| 329 | + assertEquals(expected, ft.termQuery("foo", MOCK_QSC_ENABLE_INDEX_DOC_VALUES)); |
| 330 | + } |
| 331 | + |
| 332 | + // 3.test isSearchable=false, hasDocValues=true, mappedFieldTypeName=null |
| 333 | + { |
| 334 | + FlatObjectFieldMapper.FlatObjectFieldType ft = (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType( |
| 335 | + "field", |
| 336 | + null, |
| 337 | + false, |
| 338 | + true |
| 339 | + ); |
| 340 | + Query expected = SortedSetDocValuesField.newSlowRangeQuery( |
| 341 | + "field" + VALUE_SUFFIX, |
| 342 | + new BytesRef("field.foo"), |
| 343 | + new BytesRef("field.foo"), |
| 344 | + true, |
| 345 | + true |
| 346 | + ); |
| 347 | + assertEquals(expected, ft.termQuery("foo", MOCK_QSC_ENABLE_INDEX_DOC_VALUES)); |
| 348 | + |
| 349 | + } |
| 350 | + |
| 351 | + // test isSearchable=false, hasDocValues=true, mappedFieldTypeName!=null |
| 352 | + { |
| 353 | + FlatObjectFieldMapper.FlatObjectFieldType ft = (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType( |
| 354 | + "field", |
| 355 | + "field", |
| 356 | + false, |
| 357 | + true |
| 358 | + ); |
| 359 | + Query expected = SortedSetDocValuesField.newSlowRangeQuery( |
| 360 | + "field" + VALUE_AND_PATH_SUFFIX, |
| 361 | + new BytesRef("field.foo"), |
| 362 | + new BytesRef("field.foo"), |
| 363 | + true, |
| 364 | + true |
| 365 | + ); |
| 366 | + assertEquals(expected, ft.termQuery("foo", MOCK_QSC_ENABLE_INDEX_DOC_VALUES)); |
| 367 | + } |
| 368 | + |
| 369 | + // 4.test isSearchable=false, hasDocValues=false, mappedFieldTypeName=null |
| 370 | + { |
| 371 | + FlatObjectFieldMapper.FlatObjectFieldType ft = (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType( |
| 372 | + "field", |
| 373 | + null, |
| 374 | + false, |
| 375 | + false |
| 376 | + ); |
| 377 | + IllegalArgumentException e = expectThrows( |
| 378 | + IllegalArgumentException.class, |
| 379 | + () -> ft.termQuery("foo", MOCK_QSC_ENABLE_INDEX_DOC_VALUES) |
| 380 | + ); |
| 381 | + assertEquals( |
| 382 | + "Cannot search on field [field._value] since it is both not indexed, and does not have doc_values " + "enabled.", |
| 383 | + e.getMessage() |
| 384 | + ); |
| 385 | + } |
| 386 | + |
| 387 | + // test isSearchable=false, hasDocValues=false, mappedFieldTypeName!=null |
| 388 | + { |
| 389 | + FlatObjectFieldMapper.FlatObjectFieldType ft = (FlatObjectFieldMapper.FlatObjectFieldType) getFlatParentFieldType( |
| 390 | + "field", |
| 391 | + "field", |
| 392 | + false, |
| 393 | + false |
| 394 | + ); |
| 395 | + IllegalArgumentException e = expectThrows( |
| 396 | + IllegalArgumentException.class, |
| 397 | + () -> ft.termQuery("foo", MOCK_QSC_ENABLE_INDEX_DOC_VALUES) |
| 398 | + ); |
| 399 | + assertEquals( |
| 400 | + "Cannot search on field [field._valueAndPath] since it is both not indexed, and does not have doc_values " + "enabled.", |
| 401 | + e.getMessage() |
| 402 | + ); |
| 403 | + } |
168 | 404 |
|
169 | 405 | MappedFieldType unsearchable = new FlatObjectFieldMapper.FlatObjectFieldType(
|
170 | 406 | "field",
|
171 | 407 | null,
|
172 | 408 | false,
|
173 |
| - true, |
| 409 | + false, |
174 | 410 | null,
|
175 | 411 | Collections.emptyMap()
|
176 | 412 | );
|
177 | 413 | IllegalArgumentException e = expectThrows(
|
178 | 414 | IllegalArgumentException.class,
|
179 | 415 | () -> unsearchable.termQuery("bar", MOCK_QSC_ENABLE_INDEX_DOC_VALUES)
|
180 | 416 | );
|
181 |
| - assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage()); |
| 417 | + assertEquals( |
| 418 | + "Cannot search on field [field._value] since it is both not indexed, and does not have doc_values enabled.", |
| 419 | + e.getMessage() |
| 420 | + ); |
182 | 421 | }
|
183 | 422 |
|
184 | 423 | public void testExistsQuery() {
|
|
0 commit comments