fix handling of dynamic property in mappings of sub-documents
fixes #353
This commit is contained in:
parent
3627c92f08
commit
22a54caf45
@ -127,9 +127,41 @@ func (dm *DocumentMapping) fieldDescribedByPath(path string) *FieldMapping {
|
||||
return nil
|
||||
}
|
||||
|
||||
// documentMappingForPath only returns EXACT matches for a sub document
|
||||
// or for an explicitly mapped field, if you want to find the
|
||||
// closest document mapping to a field not explicitly mapped
|
||||
// use closestDocMapping
|
||||
func (dm *DocumentMapping) documentMappingForPath(path string) *DocumentMapping {
|
||||
pathElements := decodePath(path)
|
||||
current := dm
|
||||
OUTER:
|
||||
for i, pathElement := range pathElements {
|
||||
for name, subDocMapping := range current.Properties {
|
||||
if name == pathElement {
|
||||
current = subDocMapping
|
||||
continue OUTER
|
||||
}
|
||||
}
|
||||
// no subDocMapping matches this pathElement
|
||||
// only if this is the last element check for field name
|
||||
if i == len(pathElements)-1 {
|
||||
for _, field := range current.Fields {
|
||||
if field.Name == pathElement {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
// closestDocMapping findest the most specific document mapping that matches
|
||||
// part of the provided path
|
||||
func (dm *DocumentMapping) closestDocMapping(path string) *DocumentMapping {
|
||||
pathElements := decodePath(path)
|
||||
current := dm
|
||||
OUTER:
|
||||
for _, pathElement := range pathElements {
|
||||
for name, subDocMapping := range current.Properties {
|
||||
@ -138,12 +170,6 @@ OUTER:
|
||||
continue OUTER
|
||||
}
|
||||
}
|
||||
for _, field := range current.Fields {
|
||||
if field.Name == pathElement {
|
||||
continue OUTER
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return current
|
||||
}
|
||||
@ -334,6 +360,7 @@ func (dm *DocumentMapping) processProperty(property interface{}, path []string,
|
||||
pathString := encodePath(path)
|
||||
// look to see if there is a mapping for this field
|
||||
subDocMapping := dm.documentMappingForPath(pathString)
|
||||
closestDocMapping := dm.closestDocMapping(pathString)
|
||||
|
||||
// check to see if we even need to do further processing
|
||||
if subDocMapping != nil && !subDocMapping.Enabled {
|
||||
@ -354,7 +381,7 @@ func (dm *DocumentMapping) processProperty(property interface{}, path []string,
|
||||
for _, fieldMapping := range subDocMapping.Fields {
|
||||
fieldMapping.processString(propertyValueString, pathString, path, indexes, context)
|
||||
}
|
||||
} else if dm.Dynamic {
|
||||
} else if closestDocMapping.Dynamic {
|
||||
// automatic indexing behavior
|
||||
|
||||
// first see if it can be parsed by the default date parser
|
||||
@ -385,7 +412,7 @@ func (dm *DocumentMapping) processProperty(property interface{}, path []string,
|
||||
for _, fieldMapping := range subDocMapping.Fields {
|
||||
fieldMapping.processFloat64(propertyValFloat, pathString, path, indexes, context)
|
||||
}
|
||||
} else if dm.Dynamic {
|
||||
} else if closestDocMapping.Dynamic {
|
||||
// automatic indexing behavior
|
||||
fieldMapping := newNumericFieldMappingDynamic(context.im)
|
||||
fieldMapping.processFloat64(propertyValFloat, pathString, path, indexes, context)
|
||||
@ -397,7 +424,7 @@ func (dm *DocumentMapping) processProperty(property interface{}, path []string,
|
||||
for _, fieldMapping := range subDocMapping.Fields {
|
||||
fieldMapping.processBoolean(propertyValBool, pathString, path, indexes, context)
|
||||
}
|
||||
} else if dm.Dynamic {
|
||||
} else if closestDocMapping.Dynamic {
|
||||
// automatic indexing behavior
|
||||
fieldMapping := newBooleanFieldMappingDynamic(context.im)
|
||||
fieldMapping.processBoolean(propertyValBool, pathString, path, indexes, context)
|
||||
@ -411,7 +438,7 @@ func (dm *DocumentMapping) processProperty(property interface{}, path []string,
|
||||
for _, fieldMapping := range subDocMapping.Fields {
|
||||
fieldMapping.processTime(property, pathString, path, indexes, context)
|
||||
}
|
||||
} else if dm.Dynamic {
|
||||
} else if closestDocMapping.Dynamic {
|
||||
fieldMapping := newDateTimeFieldMappingDynamic(context.im)
|
||||
fieldMapping.processTime(property, pathString, path, indexes, context)
|
||||
}
|
||||
|
@ -556,3 +556,50 @@ func TestInvalidIndexMappingStrict(t *testing.T) {
|
||||
t.Fatalf("expect to find index mapping default field 'all', got '%s'", im.DefaultField)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMappingBug353(t *testing.T) {
|
||||
dataBytes := `{
|
||||
"Reviews": [
|
||||
{
|
||||
"ReviewID": "RX16692001",
|
||||
"Content": "Usually stay near the airport..."
|
||||
}
|
||||
],
|
||||
"Other": {
|
||||
"Inside": "text"
|
||||
},
|
||||
"Name": "The Inn at Baltimore White Marsh"
|
||||
}`
|
||||
|
||||
var data map[string]interface{}
|
||||
err := json.Unmarshal([]byte(dataBytes), &data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
reviewContentFieldMapping := NewTextFieldMapping()
|
||||
reviewContentFieldMapping.Analyzer = "crazy"
|
||||
|
||||
reviewsMapping := NewDocumentMapping()
|
||||
reviewsMapping.Dynamic = false
|
||||
reviewsMapping.AddFieldMappingsAt("Content", reviewContentFieldMapping)
|
||||
otherMapping := NewDocumentMapping()
|
||||
otherMapping.Dynamic = false
|
||||
mapping := NewIndexMapping()
|
||||
mapping.DefaultMapping.AddSubDocumentMapping("Reviews", reviewsMapping)
|
||||
mapping.DefaultMapping.AddSubDocumentMapping("Other", otherMapping)
|
||||
|
||||
doc := document.NewDocument("x")
|
||||
err = mapping.mapDocument(doc, data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// expect doc has only 2 fields
|
||||
if len(doc.Fields) != 2 {
|
||||
t.Errorf("expected doc with 2 fields, got: %d", len(doc.Fields))
|
||||
for _, f := range doc.Fields {
|
||||
t.Logf("field named: %s", f.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user