in server/src/internalClusterTest/java/org/opensearch/search/query/MultiMatchQueryIT.java [703:999]
public void testCrossFieldMode() throws ExecutionException, InterruptedException {
SearchResponse searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("captain america", "full_name", "first_name", "last_name").type(
MultiMatchQueryBuilder.Type.CROSS_FIELDS
).operator(Operator.OR)
)
)
.get();
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("marvel hero captain america", "full_name", "first_name", "last_name", "category").type(
MultiMatchQueryBuilder.Type.CROSS_FIELDS
).operator(Operator.OR)
)
)
.get();
assertFirstHit(searchResponse, hasId("theother"));
assertSecondHit(searchResponse, hasId("theone"));
assertThat(searchResponse.getHits().getHits()[0].getScore(), greaterThan(searchResponse.getHits().getHits()[1].getScore()));
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("marvel hero", "full_name", "first_name", "last_name", "category").type(
MultiMatchQueryBuilder.Type.CROSS_FIELDS
).operator(Operator.OR)
)
)
.get();
assertFirstHit(searchResponse, hasId("theother"));
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("captain america", "full_name", "first_name", "last_name", "category").type(
MultiMatchQueryBuilder.Type.CROSS_FIELDS
).operator(Operator.AND)
)
)
.get();
assertHitCount(searchResponse, 1L);
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("captain america 15", "full_name", "first_name", "last_name", "category", "skill").type(
MultiMatchQueryBuilder.Type.CROSS_FIELDS
).analyzer("category").lenient(true).operator(Operator.AND)
)
)
.get();
assertHitCount(searchResponse, 1L);
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("captain america 15", "full_name", "first_name", "last_name", "category", "skill", "int-field").type(
MultiMatchQueryBuilder.Type.CROSS_FIELDS
).analyzer("category").lenient(true).operator(Operator.AND)
)
)
.get();
assertHitCount(searchResponse, 1L);
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("captain america 15", "skill", "full_name", "first_name", "last_name", "category", "int-field").type(
MultiMatchQueryBuilder.Type.CROSS_FIELDS
).analyzer("category").lenient(true).operator(Operator.AND)
)
)
.get();
assertHitCount(searchResponse, 1L);
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("captain america 15", "first_name", "last_name", "skill").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS)
.lenient(true)
.analyzer("category")
)
)
.get();
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(randomizeType(multiMatchQuery("15", "skill").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS).analyzer("category")))
.get();
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(randomizeType(multiMatchQuery("25 15", "skill").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS).analyzer("category")))
.get();
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("25 15", "int-field", "skill").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS).analyzer("category")
)
)
.get();
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("25 15", "first_name", "int-field", "skill").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS)
.analyzer("category")
)
)
.get();
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("25 15", "int-field", "skill", "first_name").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS)
.analyzer("category")
)
)
.get();
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("25 15", "int-field", "first_name", "skill").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS)
.analyzer("category")
)
)
.get();
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("captain america marvel hero", "first_name", "last_name", "category").type(
MultiMatchQueryBuilder.Type.CROSS_FIELDS
).cutoffFrequency(0.1f).analyzer("category").operator(Operator.OR)
)
)
.get();
assertFirstHit(searchResponse, anyOf(hasId("theother"), hasId("theone")));
long numResults = searchResponse.getHits().getTotalHits().value;
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("captain america marvel hero", "first_name", "last_name", "category").type(
MultiMatchQueryBuilder.Type.CROSS_FIELDS
).analyzer("category").operator(Operator.OR)
)
)
.get();
assertThat(numResults, lessThan(searchResponse.getHits().getTotalHits().value));
assertFirstHit(searchResponse, hasId("theone"));
// test group based on analyzer -- all fields are grouped into a cross field search
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("captain america marvel hero", "first_name", "last_name", "category").type(
MultiMatchQueryBuilder.Type.CROSS_FIELDS
).analyzer("category").operator(Operator.AND)
)
)
.get();
assertHitCount(searchResponse, 1L);
assertFirstHit(searchResponse, hasId("theone"));
// counter example
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("captain america marvel hero", "first_name", "last_name", "category").type(
randomBoolean() ? MultiMatchQueryBuilder.Type.CROSS_FIELDS : MultiMatchQueryBuilder.DEFAULT_TYPE
).operator(Operator.AND)
)
)
.get();
assertHitCount(searchResponse, 0L);
// counter example
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("captain america marvel hero", "first_name", "last_name", "category").type(
randomBoolean() ? MultiMatchQueryBuilder.Type.CROSS_FIELDS : MultiMatchQueryBuilder.DEFAULT_TYPE
).operator(Operator.AND)
)
)
.get();
assertHitCount(searchResponse, 0L);
// test if boosts work
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("the ultimate", "full_name", "first_name", "category").field("last_name", 10)
.type(MultiMatchQueryBuilder.Type.CROSS_FIELDS)
.operator(Operator.AND)
)
)
.get();
assertHitCount(searchResponse, 2L);
assertFirstHit(searchResponse, hasId("ultimate1")); // has ultimate in the last_name and that is boosted
assertSecondHit(searchResponse, hasId("ultimate2"));
assertThat(searchResponse.getHits().getHits()[0].getScore(), greaterThan(searchResponse.getHits().getHits()[1].getScore()));
// since we try to treat the matching fields as one field scores are very similar but we have a small bias towards the
// more frequent field that acts as a tie-breaker internally
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("the ultimate", "full_name", "first_name", "last_name", "category").type(
MultiMatchQueryBuilder.Type.CROSS_FIELDS
).operator(Operator.AND)
)
)
.get();
assertHitCount(searchResponse, 2L);
assertFirstHit(searchResponse, hasId("ultimate2"));
assertSecondHit(searchResponse, hasId("ultimate1"));
assertThat(searchResponse.getHits().getHits()[0].getScore(), greaterThan(searchResponse.getHits().getHits()[1].getScore()));
// Test group based on numeric fields
searchResponse = client().prepareSearch("test")
.setQuery(randomizeType(multiMatchQuery("15", "skill").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS)))
.get();
assertHitCount(searchResponse, 1L);
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(randomizeType(multiMatchQuery("15", "skill", "first_name").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS)))
.get();
assertHitCount(searchResponse, 1L);
assertFirstHit(searchResponse, hasId("theone"));
// Two numeric fields together caused trouble at one point!
searchResponse = client().prepareSearch("test")
.setQuery(randomizeType(multiMatchQuery("15", "int-field", "skill").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS)))
.get();
assertHitCount(searchResponse, 1L);
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(multiMatchQuery("15", "int-field", "first_name", "skill").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS))
)
.get();
assertHitCount(searchResponse, 1L);
assertFirstHit(searchResponse, hasId("theone"));
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("alpha 15", "first_name", "skill").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS).lenient(true)
)
)
.get();
assertHitCount(searchResponse, 1L);
assertFirstHit(searchResponse, hasId("ultimate1"));
/*
* Doesn't find theone because "alpha 15" isn't a number and we don't
* break on spaces.
*/
assertHitCount(searchResponse, 1);
// Lenient wasn't always properly lenient with two numeric fields
searchResponse = client().prepareSearch("test")
.setQuery(
randomizeType(
multiMatchQuery("alpha 15", "int-field", "first_name", "skill").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS)
.lenient(true)
)
)
.get();
assertHitCount(searchResponse, 1L);
assertFirstHit(searchResponse, hasId("ultimate1"));
// Check that cross fields works with date fields
searchResponse = client().prepareSearch("test")
.setQuery(randomizeType(multiMatchQuery("now", "f*", "date").type(MultiMatchQueryBuilder.Type.CROSS_FIELDS)).lenient(true))
.get();
assertHitCount(searchResponse, 1L);
assertFirstHit(searchResponse, hasId("nowHero"));
}