diff --git a/go.mod b/go.mod index 49b71da6e..0b25d0725 100644 --- a/go.mod +++ b/go.mod @@ -43,3 +43,9 @@ require ( github.com/spf13/pflag v1.0.5 // indirect golang.org/x/sys v0.13.0 // indirect ) + +replace github.com/blevesearch/bleve_index_api => ../bleve_index_api + +replace github.com/blevesearch/scorch_segment_api/v2 => ../scorch_segment_api + +replace github.com/blevesearch/zapx/v16 => ../zapx diff --git a/go.sum b/go.sum index 1914f7919..f21c89611 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/RoaringBitmap/roaring v1.9.3 h1:t4EbC5qQwnisr5PrP9nt0IRhRTb9gMUgQF4t4 github.com/RoaringBitmap/roaring v1.9.3/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90= github.com/bits-and-blooms/bitset v1.12.0 h1:U/q1fAF7xXRhFCrhROzIfffYnu+dlS38vCZtmFVPHmA= github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/blevesearch/bleve_index_api v1.2.1 h1:IuXwLvmyp7I7+e0FOA68gcHHLfzSQ4AqQ8wVab5uxk0= -github.com/blevesearch/bleve_index_api v1.2.1/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0= +github.com/blevesearch/bleve_index_api v1.2.0 h1:/DXMMWBwx/UmGKM1xDhTwDoJI5yQrG6rqRWPFcOgUVo= +github.com/blevesearch/bleve_index_api v1.2.0/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8= github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM= github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w= github.com/blevesearch/go-faiss v1.0.24 h1:K79IvKjoKHdi7FdiXEsAhxpMuns0x4fM0BO93bW5jLI= @@ -19,8 +19,8 @@ github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgY github.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+7LMvAB5IbSA= github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc= github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs= -github.com/blevesearch/scorch_segment_api/v2 v2.3.1 h1:jjexIzwOdBtC9MlUceNErYHepLvoKxTdA5atbeZSRWE= -github.com/blevesearch/scorch_segment_api/v2 v2.3.1/go.mod h1:Np3Y03rsemM5TsyFxQ3wy+tG97EcviLTbp2S5W0tpRY= +github.com/blevesearch/scorch_segment_api/v2 v2.3.0 h1:vxCjbXAkkEBSb4AB3Iqgr/EJcPyYRsiGxpcvsS8E1Dw= +github.com/blevesearch/scorch_segment_api/v2 v2.3.0/go.mod h1:5y+TgXYSx+xJGaCwSlvy9G/UJBIY5wzvIkhvhBm2ATc= github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU= github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw= github.com/blevesearch/snowball v0.6.1 h1:cDYjn/NCH+wwt2UdehaLpr2e4BwLIjN4V/TdLsL+B5A= @@ -33,18 +33,18 @@ github.com/blevesearch/upsidedown_store_api v1.0.2 h1:U53Q6YoWEARVLd1OYNc9kvhBMG github.com/blevesearch/upsidedown_store_api v1.0.2/go.mod h1:M01mh3Gpfy56Ps/UXHjEO/knbqyQ1Oamg8If49gRwrQ= github.com/blevesearch/vellum v1.1.0 h1:CinkGyIsgVlYf8Y2LUQHvdelgXr6PYuvoDIajq6yR9w= github.com/blevesearch/vellum v1.1.0/go.mod h1:QgwWryE8ThtNPxtgWJof5ndPfx0/YMBh+W2weHKPw8Y= -github.com/blevesearch/zapx/v11 v11.3.11 h1:r6/wFHFAKWvXJb82f5aO53l6p+gRH6eiX7S1tb3VGc0= -github.com/blevesearch/zapx/v11 v11.3.11/go.mod h1:0+gW+FaE48fNxoVtMY5ugtNHHof/PxCqh7CnhYdnMzQ= -github.com/blevesearch/zapx/v12 v12.3.11 h1:GBBAmXesxXLV5UZ+FZ0qILb7HPssT+kxEkbPPfp5HPM= -github.com/blevesearch/zapx/v12 v12.3.11/go.mod h1:0yeZg6JhaGxITlsS5co73aqPtM04+ycnI6D1v0mhbCs= -github.com/blevesearch/zapx/v13 v13.3.11 h1:H5ZvgS1qM1XKzsAuwp3kvDfh5sJFu9bLH/B8U6Im5e8= -github.com/blevesearch/zapx/v13 v13.3.11/go.mod h1:w2wjSDQ/WBVeEIvP0fvMJZAzDwqwIEzVPnCPrz93yAk= -github.com/blevesearch/zapx/v14 v14.3.11 h1:pg+c/YFzMJ32GkOwLzH/HAQ/GBr6y1Ar7/K5ZQpxTNo= -github.com/blevesearch/zapx/v14 v14.3.11/go.mod h1:qqyuR0u230jN1yMmE4FIAuCxmahRQEOehF78m6oTgns= -github.com/blevesearch/zapx/v15 v15.3.18 h1:yJcQnQyHGNF6rAiwq85OHn3HaXo26t7vgd83RclEw7U= -github.com/blevesearch/zapx/v15 v15.3.18/go.mod h1:vXRQzJJvlGVCdmOD5hg7t7JdjUT5DmDPhsAfjvtzIq8= -github.com/blevesearch/zapx/v16 v16.1.11-0.20250107152255-021e66397612 h1:LhORiqEVyUPUrVETzmmVuT0Yudsz2R3qGLFJWUpMsQo= -github.com/blevesearch/zapx/v16 v16.1.11-0.20250107152255-021e66397612/go.mod h1:+FIylxb+5Z/sFVmNaGpppGLHKBMUEnPSbkKoi+izER8= +github.com/blevesearch/zapx/v11 v11.3.10 h1:hvjgj9tZ9DeIqBCxKhi70TtSZYMdcFn7gDb71Xo/fvk= +github.com/blevesearch/zapx/v11 v11.3.10/go.mod h1:0+gW+FaE48fNxoVtMY5ugtNHHof/PxCqh7CnhYdnMzQ= +github.com/blevesearch/zapx/v12 v12.3.10 h1:yHfj3vXLSYmmsBleJFROXuO08mS3L1qDCdDK81jDl8s= +github.com/blevesearch/zapx/v12 v12.3.10/go.mod h1:0yeZg6JhaGxITlsS5co73aqPtM04+ycnI6D1v0mhbCs= +github.com/blevesearch/zapx/v13 v13.3.10 h1:0KY9tuxg06rXxOZHg3DwPJBjniSlqEgVpxIqMGahDE8= +github.com/blevesearch/zapx/v13 v13.3.10/go.mod h1:w2wjSDQ/WBVeEIvP0fvMJZAzDwqwIEzVPnCPrz93yAk= +github.com/blevesearch/zapx/v14 v14.3.10 h1:SG6xlsL+W6YjhX5N3aEiL/2tcWh3DO75Bnz77pSwwKU= +github.com/blevesearch/zapx/v14 v14.3.10/go.mod h1:qqyuR0u230jN1yMmE4FIAuCxmahRQEOehF78m6oTgns= +github.com/blevesearch/zapx/v15 v15.3.17 h1:NkkMI98pYLq/uHnB6YWcITrrLpCVyvZ9iP+AyfpW1Ys= +github.com/blevesearch/zapx/v15 v15.3.17/go.mod h1:vXRQzJJvlGVCdmOD5hg7t7JdjUT5DmDPhsAfjvtzIq8= +github.com/blevesearch/zapx/v16 v16.1.11-0.20241219160422-82553cdd4b38 h1:iJ3Q3sbyo2d0bjfb720RmGjj7cqzh/EdP3528ggDIMY= +github.com/blevesearch/zapx/v16 v16.1.11-0.20241219160422-82553cdd4b38/go.mod h1:JTZseJiEpogtkepKSubIKAmfgbQiOReJXfmjxB1qta4= github.com/couchbase/ghistogram v0.1.0 h1:b95QcQTCzjTUocDXp/uMgSNQi8oj1tGwnJ4bODWZnps= github.com/couchbase/ghistogram v0.1.0/go.mod h1:s1Jhy76zqfEecpNWJfWUiKZookAFaiGOEoyzgHt9i7k= github.com/couchbase/moss v0.2.0 h1:VCYrMzFwEryyhRSeI+/b3tRBSeTpi/8gn5Kf6dxqn+o= diff --git a/index_test.go b/index_test.go index c2844584a..0a781a189 100644 --- a/index_test.go +++ b/index_test.go @@ -3229,3 +3229,476 @@ func TestFuzzyScoring(t *testing.T) { t.Fatal(err) } } + +func TestDeletedFields(t *testing.T) { + + indexMapping1 := NewIndexMapping() + def1 := `{ + "analysis": {}, + "default_analyzer": "standard", + "default_datetime_parser": "dateTimeOptional", + "default_field": "_all", + "default_mapping": { + "dynamic": false, + "enabled": true, + "properties": { + "b": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "index": true, + "name": "b", + "store": true, + "type": "text" + } + ] + }, + "c": { + "dynamic": true, + "enabled": true, + "properties": { + "d": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "index": true, + "name": "b", + "store": true, + "type": "text" + } + ] + }, + "e": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "index": true, + "name": "e", + "store": true, + "type": "text" + } + ] + }, + "f": { + "dynamic": false, + "enabled": true, + "properties": { + "g": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "index": true, + "name": "g", + "store": true, + "type": "text" + } + ] + }, + "h": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "index": true, + "name": "h", + "store": true, + "type": "text" + } + ] + } + } + } + } + } + } + }, + "default_type": "_default", + "docvalues_dynamic": false, + "index_dynamic": true, + "store_dynamic": false, + "type_field": "_type", + "types": { + "geo": { + "dynamic": false, + "enabled": true, + "properties": { + "a": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "index": true, + "name": "i", + "store": true, + "type": "text" + } + ] + } + } + }, + "geo2": { + "dynamic": true, + "enabled": true, + "properties": { + "a": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "index": true, + "name": "i", + "store": true, + "type": "text" + } + ] + } + } + } + } + }` + err := indexMapping1.UnmarshalJSON([]byte(def1)) + if err != nil { + t.Fatal(err) + } + + indexMapping2 := NewIndexMapping() + def2 := `{ + "analysis": {}, + "default_analyzer": "standard", + "default_datetime_parser": "dateTimeOptional", + "default_field": "_all", + "default_mapping": { + "dynamic": false, + "enabled": true, + "properties": { + "b": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "index": true, + "name": "b", + "store": true, + "type": "text" + } + ] + }, + "c": { + "dynamic": true, + "enabled": true, + "properties": { + "d": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "index": true, + "name": "b", + "store": true, + "type": "text" + } + ] + }, + "e": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "index": true, + "name": "e", + "store": true, + "type": "text" + } + ] + }, + "f": { + "dynamic": false, + "enabled": true, + "properties": { + "h": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "index": true, + "name": "h", + "store": false, + "type": "text" + } + ] + } + } + } + } + } + } + }, + "default_type": "_default", + "docvalues_dynamic": false, + "index_dynamic": true, + "store_dynamic": false, + "type_field": "_type", + "types": { + "geo": { + "dynamic": false, + "enabled": true, + "properties": { + "a": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "index": true, + "name": "i", + "store": true, + "type": "text" + } + ] + } + } + }, + "geo2": { + "dynamic": true, + "enabled": true, + "properties": { + "a": { + "dynamic": false, + "enabled": true, + "fields": [ + { + "index": true, + "name": "i", + "store": true, + "type": "text" + } + ] + } + } + } + } + }` + err = indexMapping2.UnmarshalJSON([]byte(def2)) + if err != nil { + t.Fatal(err) + } + + _, _ = DeletedFields(indexMapping1, indexMapping2) + + fmt.Println(true) +} + +func TestIndexUpdate(t *testing.T) { + + indexMapping1 := NewIndexMapping() + + def1 := `{ + "default_analyzer": "standard", + "default_datetime_parser": "dateTimeOptional", + "default_field": "_all", + "default_mapping": { + "dynamic": false, + "enabled": false + }, + "default_type": "_default", + "docvalues_dynamic": false, + "index_dynamic": false, + "store_dynamic": false, + "type_field": "_type", + "types": { + "_default._default": { + "dynamic": false, + "enabled": true, + "properties": { + "a": { + "enabled": true, + "dynamic": false, + "fields": [ + { + "analyzer": "en", + "index": true, + "name": "a", + "type": "text", + "store": true + } + ] + }, + "b": { + "enabled": true, + "dynamic": false, + "fields": [ + { + "analyzer": "en", + "index": true, + "name": "b", + "type": "text", + "store": true + } + ] + }, + "c": { + "enabled": true, + "dynamic": false, + "fields": [ + { + "index": true, + "name": "c", + "type": "number", + "store": true + } + ] + } + } + } + } + }` + + err := indexMapping1.UnmarshalJSON([]byte(def1)) + if err != nil { + t.Fatal(err) + } + + // TestIndex1-7 old ones + // TestIndex8 a, b, c with index and store + idx, err := New("/Users/likithb/Desktop/Code/MB-57888/TestIndex8", indexMapping1) + if err != nil { + t.Fatal(err) + } + defer cleanupTmpIndexPath(t, "/Users/likithb/Desktop/Code/MB-57888/TestIndex8") + + doc1 := map[string]interface{}{"a": "001", "b": "abc", "c": 12} + doc2 := map[string]interface{}{"a": "002", "b": "def", "c": 34} + doc3 := map[string]interface{}{"a": "003", "b": "ghi", "c": 56} + doc4 := map[string]interface{}{"a": "004", "b": "jkl", "c": 78} + doc5 := map[string]interface{}{"a": "005", "b": "mno", "c": 90} + doc6 := map[string]interface{}{"a": "006", "b": "pqr", "c": 21} + doc7 := map[string]interface{}{"a": "007", "b": "stu", "c": 43} + doc8 := map[string]interface{}{"a": "008", "b": "vwx", "c": 65} + doc9 := map[string]interface{}{"a": "009", "b": "yza", "c": 87} + doc10 := map[string]interface{}{"a": "0010", "b": "bcd", "c": 9} + + batch := idx.NewBatch() + err = batch.Index("001", doc1) + if err != nil { + t.Error(err) + } + err = batch.Index("002", doc2) + if err != nil { + t.Error(err) + } + err = batch.Index("003", doc3) + if err != nil { + t.Error(err) + } + err = batch.Index("004", doc4) + if err != nil { + t.Error(err) + } + err = batch.Index("005", doc5) + if err != nil { + t.Error(err) + } + err = batch.Index("006", doc6) + if err != nil { + t.Error(err) + } + err = batch.Index("007", doc7) + if err != nil { + t.Error(err) + } + err = batch.Index("008", doc8) + if err != nil { + t.Error(err) + } + err = batch.Index("009", doc9) + if err != nil { + t.Error(err) + } + err = batch.Index("010", doc10) + if err != nil { + t.Error(err) + } + err = idx.Batch(batch) + if err != nil { + log.Fatal(err) + } + + err = idx.Close() + if err != nil { + t.Fatal(err) + } + + def2 := `{ + "default_analyzer": "standard", + "default_datetime_parser": "dateTimeOptional", + "default_field": "_all", + "default_mapping": { + "dynamic": false, + "enabled": false + }, + "default_type": "_default", + "docvalues_dynamic": false, + "index_dynamic": false, + "store_dynamic": false, + "type_field": "_type", + "types": { + "_default._default": { + "dynamic": false, + "enabled": true, + "properties": { + "a": { + "enabled": true, + "dynamic": false, + "fields": [ + { + "analyzer": "en", + "index": true, + "name": "a", + "type": "text", + "store": true + } + ] + }, + "b": { + "enabled": true, + "dynamic": false, + "fields": [ + { + "analyzer": "en", + "index": true, + "name": "b", + "type": "text", + "store": true + } + ] + }, + "c": { + "enabled": true, + "dynamic": false, + "fields": [ + { + "index": true, + "name": "c", + "type": "number", + "store": false + } + ] + } + } + } + } + }` + + idx, err = Update("/Users/likithb/Desktop/Code/MB-57888/TestIndex8", def2) + if err != nil { + t.Fatal(err) + } + + err = idx.Close() + if err != nil { + t.Fatal(err) + } +} diff --git a/index_update_test.go b/index_update_test.go new file mode 100644 index 000000000..e1d02b4cf --- /dev/null +++ b/index_update_test.go @@ -0,0 +1,372 @@ +// Copyright (c) 2025 Couchbase, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package bleve + +import ( + "reflect" + "testing" + + "github.com/blevesearch/bleve/v2/mapping" + index "github.com/blevesearch/bleve_index_api" +) + +// One full update test +// with text, vector and synonym +// verify updated index with a query +// query should check index delete, docvalues delete, store delete and all delete +// read the bolt file and the index snapshot as well +// deleted field test +// compare mappings test +// compare field mappings test +// benchmark simple queries before and after index update + +func TestCompareFieldMapping(t *testing.T) { + tests := []struct { + original *mapping.FieldMapping + updated *mapping.FieldMapping + defaultChanges *defaultInfo + indexFieldInfo *index.FieldInfo + changed bool + err bool + }{ + { // both nil => no op + original: nil, + updated: nil, + defaultChanges: nil, + indexFieldInfo: nil, + changed: false, + err: false, + }, + { // updated nil => delete all + original: &mapping.FieldMapping{}, + updated: nil, + defaultChanges: &defaultInfo{ + analyzer: false, + dateTimeParser: false, + synonymSource: false, + }, + indexFieldInfo: &index.FieldInfo{ + All: true, + }, + changed: true, + err: false, + }, + { // type changed => not updatable + original: &mapping.FieldMapping{ + Type: "text", + }, + updated: &mapping.FieldMapping{ + Type: "datetime", + }, + defaultChanges: &defaultInfo{ + analyzer: false, + dateTimeParser: false, + synonymSource: false, + }, + indexFieldInfo: nil, + changed: false, + err: true, + }, + { // synonym source changed for text => not updatable + original: &mapping.FieldMapping{ + Type: "text", + SynonymSource: "a", + }, + updated: &mapping.FieldMapping{ + Type: "text", + SynonymSource: "b", + }, + defaultChanges: &defaultInfo{ + analyzer: false, + dateTimeParser: false, + synonymSource: false, + }, + indexFieldInfo: nil, + changed: false, + err: true, + }, + { // analyser changed for text => not updatable + original: &mapping.FieldMapping{ + Type: "text", + Analyzer: "a", + }, + updated: &mapping.FieldMapping{ + Type: "text", + Analyzer: "b", + }, + defaultChanges: &defaultInfo{ + analyzer: false, + dateTimeParser: false, + synonymSource: false, + }, + indexFieldInfo: nil, + changed: false, + err: true, + }, + { // default analyser changed when inherited => not updatable + original: &mapping.FieldMapping{ + Type: "text", + Analyzer: "inherit", + }, + updated: &mapping.FieldMapping{ + Type: "text", + Analyzer: "inherit", + }, + defaultChanges: &defaultInfo{ + analyzer: true, + dateTimeParser: false, + synonymSource: false, + }, + indexFieldInfo: nil, + changed: false, + err: true, + }, + { // default datetimeparser changed for inherited datetime field => not updatable + original: &mapping.FieldMapping{ + Type: "datetime", + DateFormat: "inherit", + }, + updated: &mapping.FieldMapping{ + Type: "datetime", + DateFormat: "inherit", + }, + defaultChanges: &defaultInfo{ + analyzer: false, + dateTimeParser: true, + synonymSource: false, + }, + indexFieldInfo: nil, + changed: false, + err: true, + }, + { // dims changed for vector => not updatable + original: &mapping.FieldMapping{ + Type: "vector", + Dims: 128, + Similarity: "l2_norm", + VectorIndexOptimizedFor: "memory-efficient", + }, + updated: &mapping.FieldMapping{ + Type: "vector", + Dims: 1024, + Similarity: "l2_norm", + VectorIndexOptimizedFor: "memory-efficient", + }, + defaultChanges: &defaultInfo{ + analyzer: false, + dateTimeParser: false, + synonymSource: false, + }, + indexFieldInfo: nil, + changed: false, + err: true, + }, + { // similarity changed for vectorbase64 => not updatable + original: &mapping.FieldMapping{ + Type: "vectorbase64", + Similarity: "l2_norm", + Dims: 128, + VectorIndexOptimizedFor: "memory-efficient", + }, + updated: &mapping.FieldMapping{ + Type: "vectorbase64", + Similarity: "dot_product", + Dims: 128, + VectorIndexOptimizedFor: "memory-efficient", + }, + defaultChanges: &defaultInfo{ + analyzer: false, + dateTimeParser: false, + synonymSource: false, + }, + indexFieldInfo: nil, + changed: false, + err: true, + }, + { // vectorindexoptimizedfor chagned for vector => not updatable + original: &mapping.FieldMapping{ + Type: "vector", + Similarity: "dot_product", + Dims: 128, + VectorIndexOptimizedFor: "memory-efficient", + }, + updated: &mapping.FieldMapping{ + Type: "vector", + Similarity: "dot_product", + Dims: 128, + VectorIndexOptimizedFor: "latency", + }, + defaultChanges: &defaultInfo{ + analyzer: false, + dateTimeParser: false, + synonymSource: false, + }, + indexFieldInfo: nil, + changed: false, + err: true, + }, + { // includeinall changed => not updatable + original: &mapping.FieldMapping{ + Type: "numeric", + IncludeInAll: true, + }, + updated: &mapping.FieldMapping{ + Type: "numeric", + IncludeInAll: false, + }, + defaultChanges: &defaultInfo{ + analyzer: false, + dateTimeParser: false, + synonymSource: false, + }, + indexFieldInfo: nil, + changed: false, + err: true, + }, + { //includetermvectors changed => not updatable + original: &mapping.FieldMapping{ + Type: "numeric", + IncludeTermVectors: false, + }, + updated: &mapping.FieldMapping{ + Type: "numeric", + IncludeTermVectors: true, + }, + defaultChanges: &defaultInfo{ + analyzer: false, + dateTimeParser: false, + synonymSource: false, + }, + indexFieldInfo: nil, + changed: false, + err: true, + }, + { // store changed after all checks => updatable with store delete + original: &mapping.FieldMapping{ + Type: "numeric", + SkipFreqNorm: true, + }, + updated: &mapping.FieldMapping{ + Type: "numeric", + SkipFreqNorm: false, + }, + defaultChanges: &defaultInfo{ + analyzer: false, + dateTimeParser: false, + synonymSource: false, + }, + indexFieldInfo: nil, + changed: false, + err: true, + }, + { // index changed after all checks => updatable with index and docvalues delete + original: &mapping.FieldMapping{ + Type: "geopoint", + Index: true, + }, + updated: &mapping.FieldMapping{ + Type: "geopoint", + Index: false, + }, + defaultChanges: &defaultInfo{ + analyzer: false, + dateTimeParser: false, + synonymSource: false, + }, + indexFieldInfo: &index.FieldInfo{ + Index: true, + DocValues: true, + }, + changed: true, + err: false, + }, + { // docvalues changed after all checks => docvalues delete + original: &mapping.FieldMapping{ + Type: "numeric", + DocValues: true, + }, + updated: &mapping.FieldMapping{ + Type: "numeric", + DocValues: false, + }, + defaultChanges: &defaultInfo{ + analyzer: false, + dateTimeParser: false, + synonymSource: false, + }, + indexFieldInfo: &index.FieldInfo{ + DocValues: true, + }, + changed: true, + err: false, + }, + { // no relavent changes => continue but no op + original: &mapping.FieldMapping{ + Name: "", + Type: "datetime", + Analyzer: "a", + Store: true, + Index: false, + IncludeTermVectors: true, + IncludeInAll: false, + DateFormat: "a", + DocValues: false, + SkipFreqNorm: true, + Dims: 128, + Similarity: "dot_product", + VectorIndexOptimizedFor: "memory-efficient", + SynonymSource: "a", + }, + updated: &mapping.FieldMapping{ + Name: "", + Type: "datetime", + Analyzer: "b", + Store: true, + Index: false, + IncludeTermVectors: true, + IncludeInAll: false, + DateFormat: "a", + DocValues: false, + SkipFreqNorm: true, + Dims: 256, + Similarity: "l2_norm", + VectorIndexOptimizedFor: "latency", + SynonymSource: "b", + }, + defaultChanges: &defaultInfo{ + analyzer: false, + dateTimeParser: false, + synonymSource: false, + }, + indexFieldInfo: &index.FieldInfo{}, + changed: false, + err: false, + }, + } + + for i, test := range tests { + rv, changed, err := compareFieldMapping(test.original, test.updated, test.defaultChanges) + + if err == nil && test.err || err != nil && !test.err { + t.Errorf("Unexpected error value for test %d, expecting %s, got %v\n", i, test.err, err) + } + if changed != test.changed { + t.Errorf("Unexpected changed value for test %d, expecting %s, got %s\n", i, test.changed, changed) + } + if rv == nil && test.indexFieldInfo != nil || rv != nil && test.indexFieldInfo == nil || !reflect.DeepEqual(rv, test.indexFieldInfo) { + t.Errorf("Unexpected index field info value for test %d, expecting %+v, got %+v", i, test.indexFieldInfo, rv) + } + } +}