Repository: blevesearch/bleve
Pull request #1496 (2020-11-11 18:00:48)

fix analyzer lookup when field name contains dot
At query time, we sometimes attempt to lookup the correct
analyzer for a field.  When doing so, the "." character can
be interpretted as a path separater.  Doing this can result
in lookup failure in cases where the user specified a field
name which also contains a dot.

This fix addresses the case where the path contains a dot,
but the next element does not match a mapping at this level.
Previously this ended all looukp in this mapping, now we
attempt to match the remaining path as a whole, without
splitting on the dot.

This fix is intended to fix most common cases where a user has
given a field a name with a dot.  However, ambigutities
between custom field names containing dots, and actual mapping
paths can still happen, and must be manually avoided.

mschoch: I did a force push, which I usually avoid, to correct a typo in the commit message.

Patch:
diff --git a/mapping/document.go b/mapping/document.go
index 355a602e..dd42fab9 100644
--- a/mapping/document.go
+++ b/mapping/document.go
@@ -106,28 +106,31 @@ func (dm *DocumentMapping) fieldDescribedByPath(path string) *FieldMapping {
 				return subDocMapping.fieldDescribedByPath(encodePath(pathElements[1:]))
 			}
 		}
-	} else {
-		// just 1 path elememnt
-		// first look for property name with empty field
-		for propName, subDocMapping := range dm.Properties {
-			if propName == pathElements[0] {
-				// found property name match, now look at its fields
-				for _, field := range subDocMapping.Fields {
-					if field.Name == "" || field.Name == pathElements[0] {
-						// match
-						return field
-					}
+	}
+
+	// either the path just had one element
+	// or it had multiple, but no match for the first element at this level
+	// look for match with full path
+
+	// first look for property name with empty field
+	for propName, subDocMapping := range dm.Properties {
+		if propName == path {
+			// found property name match, now look at its fields
+			for _, field := range subDocMapping.Fields {
+				if field.Name == "" || field.Name == path {
+					// match
+					return field
 				}
 			}
 		}
-		// next, walk the properties again, looking for field overriding the name
-		for propName, subDocMapping := range dm.Properties {
-			if propName != pathElements[0] {
-				// property name isn't a match, but field name could override it
-				for _, field := range subDocMapping.Fields {
-					if field.Name == pathElements[0] {
-						return field
-					}
+	}
+	// next, walk the properties again, looking for field overriding the name
+	for propName, subDocMapping := range dm.Properties {
+		if propName != path {
+			// property name isn't a match, but field name could override it
+			for _, field := range subDocMapping.Fields {
+				if field.Name == path {
+					return field
 				}
 			}
 		}


Test patch:
diff --git a/mapping/mapping_test.go b/mapping/mapping_test.go
index 1c9ced58..564fbb21 100644
--- a/mapping/mapping_test.go
+++ b/mapping/mapping_test.go
@@ -1151,3 +1151,23 @@ func TestDefaultAnalyzerInheritance(t *testing.T) {
 		t.Fatalf("Expected analyzer: xyz to be inherited by field, but got: '%v'", analyzer)
 	}
 }
+
+func TestWrongAnalyzerSearchableAs(t *testing.T) {
+	fieldMapping := NewTextFieldMapping()
+	fieldMapping.Name = "geo.accuracy"
+	fieldMapping.Analyzer = "xyz"
+
+	nestedMapping := NewDocumentMapping()
+	nestedMapping.AddFieldMappingsAt("accuracy", fieldMapping)
+
+	docMapping := NewDocumentMapping()
+	docMapping.AddSubDocumentMapping("geo", nestedMapping)
+
+	indexMapping := NewIndexMapping()
+	indexMapping.AddDocumentMapping("brewery", docMapping)
+
+	analyzerName := indexMapping.AnalyzerNameForPath("geo.geo.accuracy")
+	if analyzerName != "xyz" {
+		t.Errorf("expected analyzer name `xyz`, got `%s`", analyzerName)
+	}
+}