Browse Source

Fix auto fuzziness in query_string query (#42897)

Setting `auto` after the fuzzy operator (e.g. `"query": "foo~auto"`) in the `query_string`
does not take the length of the term into account when computing the distance and always use
a max distance of 1. This change fixes this disrepancy by ensuring that the term is passed when
the fuzziness is computed.
Jim Ferenczi 6 years ago
parent
commit
ab25a01b65

+ 2 - 1
server/src/main/java/org/elasticsearch/index/search/QueryStringQueryParser.java

@@ -423,7 +423,8 @@ public class QueryStringQueryParser extends XQueryParser {
         if (fuzzySlop.image.length() == 1) {
             return getFuzzyQuery(field, termImage, fuzziness.asDistance(termImage));
         }
-        return getFuzzyQuery(field, termImage, Fuzziness.fromString(fuzzySlop.image.substring(1)).asFloat());
+        float distance = Fuzziness.fromString(fuzzySlop.image.substring(1)).asDistance(termImage);
+        return getFuzzyQuery(field, termImage, distance);
     }
 
     @Override

+ 28 - 19
server/src/test/java/org/elasticsearch/index/query/QueryStringQueryBuilderTests.java

@@ -786,27 +786,36 @@ public class QueryStringQueryBuilderTests extends FullTextQueryTestCase<QueryStr
     }
 
     public void testToQueryFuzzyQueryAutoFuziness() throws Exception {
-        int length = randomIntBetween(1, 10);
-        StringBuilder queryString = new StringBuilder();
-        for (int i = 0; i < length; i++) {
-            queryString.append("a");
-        }
-        queryString.append("~");
+        for (int i = 0; i < 3; i++) {
+            final int expectedEdits;
+            String queryString;
+            switch (i) {
+                case 0:
+                    queryString = randomAlphaOfLengthBetween(1, 2);
+                    expectedEdits = 0;
+                    break;
+
+                case 1:
+                    queryString = randomAlphaOfLengthBetween(3, 5);
+                    expectedEdits = 1;
+                    break;
+
+                default:
+                    queryString = randomAlphaOfLengthBetween(6, 20);
+                    expectedEdits = 2;
+                    break;
+            }
 
-        int expectedEdits;
-        if (length <= 2) {
-            expectedEdits = 0;
-        } else if (3 <= length && length <= 5) {
-            expectedEdits = 1;
-        } else {
-            expectedEdits = 2;
+            for (int j = 0; j < 2; j++) {
+                Query query = queryStringQuery(queryString + (j == 0 ? "~" : "~auto"))
+                    .defaultField(STRING_FIELD_NAME)
+                    .fuzziness(Fuzziness.AUTO)
+                    .toQuery(createShardContext());
+                assertThat(query, instanceOf(FuzzyQuery.class));
+                FuzzyQuery fuzzyQuery = (FuzzyQuery) query;
+                assertEquals(expectedEdits, fuzzyQuery.getMaxEdits());
+            }
         }
-
-        Query query = queryStringQuery(queryString.toString()).defaultField(STRING_FIELD_NAME).fuzziness(Fuzziness.AUTO)
-            .toQuery(createShardContext());
-        assertThat(query, instanceOf(FuzzyQuery.class));
-        FuzzyQuery fuzzyQuery = (FuzzyQuery) query;
-        assertEquals(expectedEdits, fuzzyQuery.getMaxEdits());
     }
 
     public void testFuzzyNumeric() throws Exception {