github.com/weaviate/weaviate@v1.24.6/test/acceptance/graphql_resolvers/setup_test.go (about)

     1  //                           _       _
     2  // __      _____  __ ___   ___  __ _| |_ ___
     3  // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
     4  //  \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
     5  //   \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
     6  //
     7  //  Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
     8  //
     9  //  CONTACT: hello@weaviate.io
    10  //
    11  
    12  package test
    13  
    14  import (
    15  	"context"
    16  	"fmt"
    17  	"math/rand"
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/go-openapi/strfmt"
    22  	"github.com/google/uuid"
    23  	"github.com/stretchr/testify/require"
    24  	"github.com/weaviate/weaviate/entities/models"
    25  	"github.com/weaviate/weaviate/entities/schema"
    26  	"github.com/weaviate/weaviate/entities/schema/crossref"
    27  	"github.com/weaviate/weaviate/test/docker"
    28  	"github.com/weaviate/weaviate/test/helper"
    29  	"github.com/weaviate/weaviate/test/helper/sample-schema/multishard"
    30  )
    31  
    32  func TestGraphQL_AsyncIndexing(t *testing.T) {
    33  	ctx := context.Background()
    34  	compose, err := docker.New().
    35  		WithWeaviate().
    36  		WithText2VecContextionary().
    37  		WithBackendFilesystem().
    38  		WithWeaviateEnv("ASYNC_INDEXING", "true").
    39  		Start(ctx)
    40  	require.NoError(t, err)
    41  	defer func() {
    42  		require.NoError(t, compose.Terminate(ctx))
    43  	}()
    44  
    45  	defer helper.SetupClient(fmt.Sprintf("%s:%s", helper.ServerHost, helper.ServerPort))
    46  	helper.SetupClient(compose.GetWeaviate().URI())
    47  
    48  	testGraphQL(t)
    49  }
    50  
    51  func TestGraphQL_SyncIndexing(t *testing.T) {
    52  	testGraphQL(t)
    53  }
    54  
    55  func testGraphQL(t *testing.T) {
    56  	// tests with classes that have objects with same uuids
    57  	t.Run("import test data (near object search class)", addTestDataNearObjectSearch)
    58  
    59  	t.Run("running Get nearObject against shadowed objects", runningGetNearObjectWithShadowedObjects)
    60  	t.Run("running Aggregate nearObject against shadowed objects", runningAggregateNearObjectWithShadowedObjects)
    61  	t.Run("running Explore nearObject against shadowed objects", runningExploreNearObjectWithShadowedObjects)
    62  
    63  	deleteObjectClass(t, "NearObjectSearch")
    64  	deleteObjectClass(t, "NearObjectSearchShadow")
    65  
    66  	// setup tests
    67  	t.Run("setup test schema", addTestSchema)
    68  	t.Run("import test data (city, country, airport)", addTestDataCityAirport)
    69  	t.Run("import test data (companies)", addTestDataCompanies)
    70  	t.Run("import test data (person)", addTestDataPersons)
    71  	t.Run("import test data (pizzas)", addTestDataPizzas)
    72  	t.Run("import test data (array class)", addTestDataArrayClass)
    73  	t.Run("import test data (duplicates class)", addTestDataDuplicatesClass)
    74  	t.Run("import test data (500 random strings)", addTestDataRansomNotes)
    75  	t.Run("import test data (multi shard)", addTestDataMultiShard)
    76  	t.Run("import test data (date field class)", addDateFieldClass)
    77  	t.Run("import test data (custom vector class)", addTestDataCVC)
    78  	t.Run("import test data (class without properties)", addTestDataNoProperties)
    79  	t.Run("import test data (cursor api)", addTestDataCursorSearch)
    80  
    81  	// explore tests
    82  	t.Run("expected explore failures with invalid conditions", exploreWithExpectedFailures)
    83  
    84  	// get tests
    85  	t.Run("getting objects", gettingObjects)
    86  	t.Run("getting objects with filters", gettingObjectsWithFilters)
    87  	t.Run("getting objects with geo filters", gettingObjectsWithGeoFilters)
    88  	t.Run("getting objects with grouping", gettingObjectsWithGrouping)
    89  	t.Run("getting objects with additional props", gettingObjectsWithAdditionalProps)
    90  	t.Run("getting objects with near fields", gettingObjectsWithNearFields)
    91  	t.Run("getting objects with near fields with multi shard setup", gettingObjectsWithNearFieldsMultiShard)
    92  	t.Run("getting objects with sort", gettingObjectsWithSort)
    93  	t.Run("getting objects with hybrid search", getWithHybridSearch)
    94  	t.Run("expected get failures with invalid conditions", getsWithExpectedFailures)
    95  	t.Run("cursor through results", getWithCursorSearch)
    96  	t.Run("groupBy objects", groupByObjects)
    97  
    98  	// aggregate tests
    99  	t.Run("aggregates noPropsClass without grouping", aggregateNoPropsClassWithoutGroupByTest)
   100  	t.Run("aggregates arrayClass without grouping", aggregateArrayClassWithoutGroupByTest)
   101  	t.Run("aggregates arrayClass with grouping", aggregateArrayClassWithGroupByTest)
   102  	t.Run("aggregates duplicatesClass without grouping", aggregateDuplicatesClassWithoutGroupByTest)
   103  	t.Run("aggregates duplicatesClass with grouping", aggregateDuplicatesClassWithGroupByTest)
   104  	t.Run("aggregates city without grouping", aggregateCityClassWithoutGroupByTest)
   105  	t.Run("aggregates city with grouping", aggregateCityClassWithGroupByTest)
   106  
   107  	t.Run("aggregates local meta string props not set everywhere", localMeta_StringPropsNotSetEverywhere)
   108  	t.Run("aggregates local meta with where and nearText filters", localMetaWithWhereAndNearTextFilters)
   109  	t.Run("aggregates local meta with where and nearObject filters", localMetaWithWhereAndNearObjectFilters)
   110  	t.Run("aggregates local meta with nearVector filters", localMetaWithNearVectorFilter)
   111  	t.Run("aggregates local meta with where and nearVector nearMedia", localMetaWithWhereAndNearVectorFilters)
   112  	t.Run("aggregates local meta with where groupBy and nearMedia filters", localMetaWithWhereGroupByNearMediaFilters)
   113  	t.Run("aggregates local meta with objectLimit and nearMedia filters", localMetaWithObjectLimit)
   114  	t.Run("aggregates on date fields", aggregatesOnDateFields)
   115  	t.Run("aggregates with hybrid search", aggregationWithHybridSearch)
   116  	t.Run("expected aggregate failures with invalid conditions", aggregatesWithExpectedFailures)
   117  
   118  	t.Run("metrics count is stable when more classes are added", metricsCount)
   119  
   120  	// tear down
   121  	deleteObjectClass(t, "Person")
   122  	deleteObjectClass(t, "Pizza")
   123  	deleteObjectClass(t, "Country")
   124  	deleteObjectClass(t, "City")
   125  	deleteObjectClass(t, "Airport")
   126  	deleteObjectClass(t, "Company")
   127  	deleteObjectClass(t, "RansomNote")
   128  	deleteObjectClass(t, "MultiShard")
   129  	deleteObjectClass(t, "HasDateField")
   130  	deleteObjectClass(t, arrayClassName)
   131  	deleteObjectClass(t, duplicatesClassName)
   132  	deleteObjectClass(t, noPropsClassName)
   133  	deleteObjectClass(t, "CursorClass")
   134  
   135  	// only run after everything else is deleted, this way, we can also run an
   136  	// all-class Explore since all vectors which are now left have the same
   137  	// dimensions.
   138  
   139  	t.Run("getting objects with custom vectors", gettingObjectsWithCustomVectors)
   140  	t.Run("explore objects with custom vectors", exploreObjectsWithCustomVectors)
   141  
   142  	deleteObjectClass(t, "CustomVectorClass")
   143  }
   144  
   145  func addTestSchema(t *testing.T) {
   146  	createObjectClass(t, &models.Class{
   147  		Class: "Country",
   148  		ModuleConfig: map[string]interface{}{
   149  			"text2vec-contextionary": map[string]interface{}{
   150  				"vectorizeClassName": true,
   151  			},
   152  		},
   153  		Properties: []*models.Property{
   154  			{
   155  				Name:         "name",
   156  				DataType:     schema.DataTypeText.PropString(),
   157  				Tokenization: models.PropertyTokenizationWhitespace,
   158  			},
   159  		},
   160  	})
   161  
   162  	// City class has only one vectorizable field: "name"
   163  	// the rest of the fields are explicitly set to skip vectorization
   164  	// to not to downgrade the distance/certainty result on which the
   165  	// aggregate tests are based on.
   166  	createObjectClass(t, &models.Class{
   167  		Class: "City",
   168  		ModuleConfig: map[string]interface{}{
   169  			"text2vec-contextionary": map[string]interface{}{
   170  				"vectorizeClassName": true,
   171  			},
   172  		},
   173  		InvertedIndexConfig: &models.InvertedIndexConfig{IndexNullState: true, IndexPropertyLength: true, IndexTimestamps: true},
   174  		Properties: []*models.Property{
   175  			{
   176  				Name:         "name",
   177  				DataType:     schema.DataTypeText.PropString(),
   178  				Tokenization: models.PropertyTokenizationWhitespace,
   179  				ModuleConfig: map[string]interface{}{
   180  					"text2vec-contextionary": map[string]interface{}{
   181  						"skip": false,
   182  					},
   183  				},
   184  			},
   185  			{
   186  				Name:     "inCountry",
   187  				DataType: []string{"Country"},
   188  				ModuleConfig: map[string]interface{}{
   189  					"text2vec-contextionary": map[string]interface{}{
   190  						"skip": true,
   191  					},
   192  				},
   193  			},
   194  			{
   195  				Name:     "population",
   196  				DataType: []string{"int"},
   197  				ModuleConfig: map[string]interface{}{
   198  					"text2vec-contextionary": map[string]interface{}{
   199  						"skip": true,
   200  					},
   201  				},
   202  			},
   203  			{
   204  				Name:     "location",
   205  				DataType: []string{"geoCoordinates"},
   206  				ModuleConfig: map[string]interface{}{
   207  					"text2vec-contextionary": map[string]interface{}{
   208  						"skip": true,
   209  					},
   210  				},
   211  			},
   212  			{
   213  				Name:     "isCapital",
   214  				DataType: []string{"boolean"},
   215  				ModuleConfig: map[string]interface{}{
   216  					"text2vec-contextionary": map[string]interface{}{
   217  						"skip": true,
   218  					},
   219  				},
   220  			},
   221  			{
   222  				Name:     "cityArea",
   223  				DataType: []string{"number"},
   224  				ModuleConfig: map[string]interface{}{
   225  					"text2vec-contextionary": map[string]interface{}{
   226  						"skip": true,
   227  					},
   228  				},
   229  			},
   230  			{
   231  				Name:     "cityRights",
   232  				DataType: []string{"date"},
   233  				ModuleConfig: map[string]interface{}{
   234  					"text2vec-contextionary": map[string]interface{}{
   235  						"skip": true,
   236  					},
   237  				},
   238  			},
   239  			{
   240  				Name:         "timezones",
   241  				DataType:     schema.DataTypeTextArray.PropString(),
   242  				Tokenization: models.PropertyTokenizationWhitespace,
   243  				ModuleConfig: map[string]interface{}{
   244  					"text2vec-contextionary": map[string]interface{}{
   245  						"skip": true,
   246  					},
   247  				},
   248  			},
   249  			{
   250  				Name:     "museums",
   251  				DataType: []string{"text[]"},
   252  				ModuleConfig: map[string]interface{}{
   253  					"text2vec-contextionary": map[string]interface{}{
   254  						"skip": true,
   255  					},
   256  				},
   257  			},
   258  			{
   259  				Name:     "history",
   260  				DataType: []string{"text"},
   261  				ModuleConfig: map[string]interface{}{
   262  					"text2vec-contextionary": map[string]interface{}{
   263  						"skip": true,
   264  					},
   265  				},
   266  			},
   267  			{
   268  				Name:     "phoneNumber",
   269  				DataType: []string{"phoneNumber"},
   270  				ModuleConfig: map[string]interface{}{
   271  					"text2vec-contextionary": map[string]interface{}{
   272  						"skip": true,
   273  					},
   274  				},
   275  			},
   276  		},
   277  	})
   278  
   279  	createObjectClass(t, &models.Class{
   280  		Class: "Airport",
   281  		ModuleConfig: map[string]interface{}{
   282  			"text2vec-contextionary": map[string]interface{}{
   283  				"vectorizeClassName": true,
   284  			},
   285  		},
   286  		InvertedIndexConfig: &models.InvertedIndexConfig{
   287  			CleanupIntervalSeconds: 60,
   288  			Stopwords: &models.StopwordConfig{
   289  				Preset: "en",
   290  			},
   291  			IndexTimestamps: true,
   292  		},
   293  		Properties: []*models.Property{
   294  			{
   295  				Name:         "code",
   296  				DataType:     schema.DataTypeText.PropString(),
   297  				Tokenization: models.PropertyTokenizationWhitespace,
   298  			},
   299  			{
   300  				Name:     "phone",
   301  				DataType: []string{"phoneNumber"},
   302  			},
   303  			{
   304  				Name:     "inCity",
   305  				DataType: []string{"City"},
   306  			},
   307  			{
   308  				Name:     "airportId",
   309  				DataType: []string{"uuid"},
   310  			},
   311  		},
   312  	})
   313  
   314  	createObjectClass(t, &models.Class{
   315  		Class: "Company",
   316  		ModuleConfig: map[string]interface{}{
   317  			"text2vec-contextionary": map[string]interface{}{
   318  				"vectorizeClassName": false,
   319  			},
   320  		},
   321  		Properties: []*models.Property{
   322  			{
   323  				Name:         "name",
   324  				DataType:     schema.DataTypeText.PropString(),
   325  				Tokenization: models.PropertyTokenizationWhitespace,
   326  				ModuleConfig: map[string]interface{}{
   327  					"text2vec-contextionary": map[string]interface{}{
   328  						"vectorizePropertyName": false,
   329  					},
   330  				},
   331  			},
   332  			{
   333  				Name:     "inCity",
   334  				DataType: []string{"City"},
   335  				ModuleConfig: map[string]interface{}{
   336  					"text2vec-contextionary": map[string]interface{}{
   337  						"vectorizePropertyName": false,
   338  					},
   339  				},
   340  			},
   341  		},
   342  	})
   343  
   344  	createObjectClass(t, &models.Class{
   345  		Class: "Person",
   346  		ModuleConfig: map[string]interface{}{
   347  			"text2vec-contextionary": map[string]interface{}{
   348  				"vectorizeClassName": false,
   349  			},
   350  		},
   351  		Properties: []*models.Property{
   352  			{
   353  				Name:         "name",
   354  				DataType:     schema.DataTypeText.PropString(),
   355  				Tokenization: models.PropertyTokenizationWhitespace,
   356  				ModuleConfig: map[string]interface{}{
   357  					"text2vec-contextionary": map[string]interface{}{
   358  						"vectorizePropertyName": false,
   359  					},
   360  				},
   361  			},
   362  			{
   363  				Name:     "livesIn",
   364  				DataType: []string{"City"},
   365  				ModuleConfig: map[string]interface{}{
   366  					"text2vec-contextionary": map[string]interface{}{
   367  						"vectorizePropertyName": false,
   368  					},
   369  				},
   370  			},
   371  			{
   372  				Name:         "profession",
   373  				DataType:     schema.DataTypeText.PropString(),
   374  				Tokenization: models.PropertyTokenizationField,
   375  				ModuleConfig: map[string]interface{}{
   376  					"text2vec-contextionary": map[string]interface{}{
   377  						"vectorizePropertyName": false,
   378  					},
   379  				},
   380  			},
   381  			{
   382  				Name:         "about",
   383  				DataType:     schema.DataTypeTextArray.PropString(),
   384  				Tokenization: models.PropertyTokenizationField,
   385  				ModuleConfig: map[string]interface{}{
   386  					"text2vec-contextionary": map[string]interface{}{
   387  						"vectorizePropertyName": false,
   388  					},
   389  				},
   390  			},
   391  		},
   392  	})
   393  
   394  	createObjectClass(t, &models.Class{
   395  		Class: "Pizza",
   396  		ModuleConfig: map[string]interface{}{
   397  			"text2vec-contextionary": map[string]interface{}{
   398  				"vectorizeClassName": false,
   399  			},
   400  		},
   401  		Properties: []*models.Property{
   402  			{
   403  				Name:         "name",
   404  				DataType:     schema.DataTypeText.PropString(),
   405  				Tokenization: models.PropertyTokenizationField,
   406  				ModuleConfig: map[string]interface{}{
   407  					"text2vec-contextionary": map[string]interface{}{
   408  						"vectorizePropertyName": false,
   409  					},
   410  				},
   411  			},
   412  			{
   413  				Name:         "description",
   414  				DataType:     []string{string(schema.DataTypeText)},
   415  				Tokenization: models.PropertyTokenizationWord,
   416  				ModuleConfig: map[string]interface{}{
   417  					"text2vec-contextionary": map[string]interface{}{
   418  						"vectorizePropertyName": false,
   419  					},
   420  				},
   421  			},
   422  		},
   423  	})
   424  
   425  	createObjectClass(t, &models.Class{
   426  		Class: "RansomNote",
   427  		ModuleConfig: map[string]interface{}{
   428  			"text2vec-contextionary": map[string]interface{}{
   429  				"vectorizeClassName": true,
   430  			},
   431  		},
   432  		Properties: []*models.Property{
   433  			{
   434  				Name:         "contents",
   435  				DataType:     schema.DataTypeText.PropString(),
   436  				Tokenization: models.PropertyTokenizationWhitespace,
   437  			},
   438  		},
   439  	})
   440  
   441  	createObjectClass(t, multishard.ClassContextionaryVectorizer())
   442  
   443  	createObjectClass(t, &models.Class{
   444  		Class: "HasDateField",
   445  		ModuleConfig: map[string]interface{}{
   446  			"text2vec-contextionary": map[string]interface{}{
   447  				"vectorizeClassName": true,
   448  			},
   449  		},
   450  		Properties: []*models.Property{
   451  			{
   452  				Name:         "unique",
   453  				DataType:     schema.DataTypeText.PropString(),
   454  				Tokenization: models.PropertyTokenizationWhitespace,
   455  			},
   456  			{
   457  				Name:     "timestamp",
   458  				DataType: []string{"date"},
   459  			},
   460  			{
   461  				Name:         "identical",
   462  				DataType:     schema.DataTypeText.PropString(),
   463  				Tokenization: models.PropertyTokenizationWhitespace,
   464  			},
   465  		},
   466  	})
   467  
   468  	createObjectClass(t, &models.Class{
   469  		Class:      "CustomVectorClass",
   470  		Vectorizer: "none",
   471  		Properties: []*models.Property{
   472  			{
   473  				Name:         "name",
   474  				DataType:     schema.DataTypeText.PropString(),
   475  				Tokenization: models.PropertyTokenizationWhitespace,
   476  			},
   477  		},
   478  	})
   479  
   480  	createObjectClass(t, noPropsClassSchema())
   481  	createObjectClass(t, arrayClassSchema())
   482  	createObjectClass(t, duplicatesClassSchema())
   483  }
   484  
   485  const (
   486  	netherlands   strfmt.UUID = "67b79643-cf8b-4b22-b206-6e63dbb4e57a"
   487  	germany       strfmt.UUID = "561eea29-b733-4079-b50b-cfabd78190b7"
   488  	amsterdam     strfmt.UUID = "8f5f8e44-d348-459c-88b1-c1a44bb8f8be"
   489  	rotterdam     strfmt.UUID = "660db307-a163-41d2-8182-560782cd018f"
   490  	berlin        strfmt.UUID = "9b9cbea5-e87e-4cd0-89af-e2f424fd52d6"
   491  	dusseldorf    strfmt.UUID = "6ffb03f8-a853-4ec5-a5d8-302e45aaaf13"
   492  	missingisland strfmt.UUID = "823abeca-eef3-41c7-b587-7a6977b08003"
   493  	nullisland    strfmt.UUID = "823abeca-eef3-41c7-b587-7a6977b08067"
   494  	airport1      strfmt.UUID = "4770bb19-20fd-406e-ac64-9dac54c27a0f"
   495  	airport2      strfmt.UUID = "cad6ab9b-5bb9-4388-a933-a5bdfd23db37"
   496  	airport3      strfmt.UUID = "55a4dbbb-e2af-4b2a-901d-98146d1eeca7"
   497  	airport4      strfmt.UUID = "62d15920-b546-4844-bc87-3ae33268fab5"
   498  	cvc1          strfmt.UUID = "1ffeb3e1-1258-4c2a-afc3-55543f6c44b8"
   499  	cvc2          strfmt.UUID = "df22e5c4-5d17-49f9-a71d-f392a82bc086"
   500  	cvc3          strfmt.UUID = "c28a039a-d509-4c2e-940a-8b109e5bebf4"
   501  
   502  	quattroFormaggi strfmt.UUID = "152500c6-4a8a-4732-aede-9fcab7e43532"
   503  	fruttiDiMare    strfmt.UUID = "a828e9aa-d1b6-4644-8569-30d404e31a0d"
   504  	hawaii          strfmt.UUID = "ed75037b-0748-4970-811e-9fe835ed41d1"
   505  	doener          strfmt.UUID = "a655292d-1b93-44a1-9a47-57b6922bb455"
   506  )
   507  
   508  var (
   509  	historyAmsterdam  = "Due to its geographical location in what used to be wet peatland, the founding of Amsterdam is of a younger age than the founding of other urban centers in the Low Countries. However, in and around the area of what later became Amsterdam, local farmers settled as early as three millennia ago. They lived along the prehistoric IJ river and upstream of its tributary Amstel. The prehistoric IJ was a shallow and quiet stream in peatland behind beach ridges. This secluded area could grow there into an important local settlement center, especially in the late Bronze Age, the Iron Age and the Roman Age. Neolithic and Roman artefacts have also been found downstream of this area, in the prehistoric Amstel bedding under Amsterdam's Damrak and Rokin, such as shards of Bell Beaker culture pottery (2200-2000 BC) and a granite grinding stone (2700-2750 BC).[27][28] But the location of these artefacts around the river banks of the Amstel probably point to a presence of a modest semi-permanent or seasonal settlement of the previous mentioned local farmers. A permanent settlement would not have been possible, since the river mouth and the banks of the Amstel in this period in time were too wet for permanent habitation"
   510  	historyRotterdam  = "On 7 July 1340, Count Willem IV of Holland granted city rights to Rotterdam, whose population then was only a few thousand.[14] Around the year 1350, a shipping canal (the Rotterdamse Schie) was completed, which provided Rotterdam access to the larger towns in the north, allowing it to become a local trans-shipment centre between the Netherlands, England and Germany, and to urbanize"
   511  	historyBerlin     = "The earliest evidence of settlements in the area of today's Berlin are remnants of a house foundation dated to 1174, found in excavations in Berlin Mitte,[27] and a wooden beam dated from approximately 1192.[28] The first written records of towns in the area of present-day Berlin date from the late 12th century. Spandau is first mentioned in 1197 and Köpenick in 1209, although these areas did not join Berlin until 1920.[29] The central part of Berlin can be traced back to two towns. Cölln on the Fischerinsel is first mentioned in a 1237 document, and Berlin, across the Spree in what is now called the Nikolaiviertel, is referenced in a document from 1244.[28] 1237 is considered the founding date of the city.[30] The two towns over time formed close economic and social ties, and profited from the staple right on the two important trade routes Via Imperii and from Bruges to Novgorod.[12] In 1307, they formed an alliance with a common external policy, their internal administrations still being separated"
   512  	historyDusseldorf = "The first written mention of Düsseldorf (then called Dusseldorp in the local Low Rhenish dialect) dates back to 1135. Under Emperor Friedrich Barbarossa the small town of Kaiserswerth to the north of Düsseldorf became a well-fortified outpost, where soldiers kept a watchful eye on every movement on the Rhine. Kaiserswerth eventually became a suburb of Düsseldorf in 1929. In 1186, Düsseldorf came under the rule of the Counts of Berg. 14 August 1288 is one of the most important dates in the history of Düsseldorf. On this day the sovereign Count Adolf VIII of Berg granted the village on the banks of the Düssel town privileges. Before this, a bloody struggle for power had taken place between the Archbishop of Cologne and the count of Berg, culminating in the Battle of Worringen"
   513  )
   514  
   515  func addTestDataCityAirport(t *testing.T) {
   516  	// countries
   517  	createObject(t, &models.Object{
   518  		Class: "Country",
   519  		ID:    netherlands,
   520  		Properties: map[string]interface{}{
   521  			"name": "Netherlands",
   522  		},
   523  	})
   524  	createObject(t, &models.Object{
   525  		Class: "Country",
   526  		ID:    germany,
   527  		Properties: map[string]interface{}{
   528  			"name": "Germany",
   529  		},
   530  	})
   531  
   532  	// cities
   533  	createObject(t, &models.Object{
   534  		Class: "City",
   535  		ID:    amsterdam,
   536  		Properties: map[string]interface{}{
   537  			"name":       "Amsterdam",
   538  			"population": 1800000,
   539  			"location": map[string]interface{}{
   540  				"latitude":  52.366667,
   541  				"longitude": 4.9,
   542  			},
   543  			"inCountry": []interface{}{
   544  				map[string]interface{}{
   545  					"beacon": crossref.NewLocalhost("Country", netherlands).String(),
   546  				},
   547  			},
   548  			"isCapital":  true,
   549  			"cityArea":   float64(891.95),
   550  			"cityRights": mustParseYear("1400"),
   551  			"timezones":  []string{"CET", "CEST"},
   552  			"museums":    []string{"Stedelijk Museum", "Rijksmuseum"},
   553  			"history":    historyAmsterdam,
   554  			"phoneNumber": map[string]interface{}{
   555  				"input": "+311000004",
   556  			},
   557  		},
   558  	})
   559  	createObject(t, &models.Object{
   560  		Class: "City",
   561  		ID:    rotterdam,
   562  		Properties: map[string]interface{}{
   563  			"name":       "Rotterdam",
   564  			"population": 600000,
   565  			"inCountry": []interface{}{
   566  				map[string]interface{}{
   567  					"beacon": crossref.NewLocalhost("Country", netherlands).String(),
   568  				},
   569  			},
   570  			"isCapital":  false,
   571  			"cityArea":   float64(319.35),
   572  			"cityRights": mustParseYear("1283"),
   573  			"timezones":  []string{"CET", "CEST"},
   574  			"museums":    []string{"Museum Boijmans Van Beuningen", "Wereldmuseum", "Witte de With Center for Contemporary Art"},
   575  			"history":    historyRotterdam,
   576  			"phoneNumber": map[string]interface{}{
   577  				"input": "+311000000",
   578  			},
   579  		},
   580  	})
   581  	createObject(t, &models.Object{
   582  		Class: "City",
   583  		ID:    berlin,
   584  		Properties: map[string]interface{}{
   585  			"name":       "Berlin",
   586  			"population": 3470000,
   587  			"inCountry": []interface{}{
   588  				map[string]interface{}{
   589  					"beacon": crossref.NewLocalhost("Country", germany).String(),
   590  				},
   591  			},
   592  			"isCapital":  true,
   593  			"cityArea":   float64(891.96),
   594  			"cityRights": mustParseYear("1400"),
   595  			"timezones":  []string{"CET", "CEST"},
   596  			"museums":    []string{"German Historical Museum"},
   597  			"history":    historyBerlin,
   598  			"phoneNumber": map[string]interface{}{
   599  				"input": "+311000002",
   600  			},
   601  		},
   602  	})
   603  	createObject(t, &models.Object{
   604  		Class: "City",
   605  		ID:    dusseldorf,
   606  		Properties: map[string]interface{}{
   607  			"name":       "Dusseldorf",
   608  			"population": 600000,
   609  			"inCountry": []interface{}{
   610  				map[string]interface{}{
   611  					"beacon": crossref.NewLocalhost("Country", germany).String(),
   612  				},
   613  			},
   614  			"location": map[string]interface{}{
   615  				"latitude":  51.225556,
   616  				"longitude": 6.782778,
   617  			},
   618  			"isCapital":  false,
   619  			"cityArea":   float64(217.22),
   620  			"cityRights": mustParseYear("1135"),
   621  			"timezones":  []string{"CET", "CEST"},
   622  			"museums":    []string{"Schlossturm", "Schiffahrt Museum", "Onomato"},
   623  			"history":    historyDusseldorf,
   624  			"phoneNumber": map[string]interface{}{
   625  				"input": "+311000001",
   626  			},
   627  		},
   628  	})
   629  
   630  	createObject(t, &models.Object{
   631  		Class: "City",
   632  		ID:    missingisland,
   633  		Properties: map[string]interface{}{
   634  			"name":       "Missing Island",
   635  			"population": 0,
   636  			"location": map[string]interface{}{
   637  				"latitude":  0,
   638  				"longitude": 0,
   639  			},
   640  			"isCapital": false,
   641  		},
   642  	})
   643  
   644  	createObject(t, &models.Object{
   645  		Class: "City",
   646  		ID:    nullisland,
   647  		Properties: map[string]interface{}{
   648  			"name":        nil,
   649  			"population":  nil,
   650  			"inCountry":   nil,
   651  			"location":    nil,
   652  			"isCapital":   nil,
   653  			"cityArea":    nil,
   654  			"cityRights":  nil,
   655  			"timezones":   nil,
   656  			"museums":     nil,
   657  			"history":     nil,
   658  			"phoneNumber": nil,
   659  		},
   660  	})
   661  
   662  	// airports
   663  	createObject(t, &models.Object{
   664  		Class: "Airport",
   665  		ID:    airport1,
   666  		Properties: map[string]interface{}{
   667  			"code":      "10000",
   668  			"airportId": uuid.MustParse("00000000-0000-0000-0000-000000010000").String(),
   669  			"phone": map[string]interface{}{
   670  				"input": "+311234567",
   671  			},
   672  			"inCity": []interface{}{
   673  				map[string]interface{}{
   674  					"beacon": crossref.NewLocalhost("City", amsterdam).String(),
   675  				},
   676  			},
   677  		},
   678  	})
   679  	createObject(t, &models.Object{
   680  		Class: "Airport",
   681  		ID:    airport2,
   682  		Properties: map[string]interface{}{
   683  			"code":      "20000",
   684  			"airportId": uuid.MustParse("00000000-0000-0000-0000-000000020000").String(),
   685  			"inCity": []interface{}{
   686  				map[string]interface{}{
   687  					"beacon": crossref.NewLocalhost("City", rotterdam).String(),
   688  				},
   689  			},
   690  		},
   691  	})
   692  	createObject(t, &models.Object{
   693  		Class: "Airport",
   694  		ID:    airport3,
   695  		Properties: map[string]interface{}{
   696  			"code":      "30000",
   697  			"airportId": uuid.MustParse("00000000-0000-0000-0000-000000030000").String(),
   698  			"inCity": []interface{}{
   699  				map[string]interface{}{
   700  					"beacon": crossref.NewLocalhost("City", dusseldorf).String(),
   701  				},
   702  			},
   703  		},
   704  	})
   705  	createObject(t, &models.Object{
   706  		Class: "Airport",
   707  		ID:    airport4,
   708  		Properties: map[string]interface{}{
   709  			"code":      "40000",
   710  			"airportId": uuid.MustParse("00000000-0000-0000-0000-000000040000").String(),
   711  			"inCity": []interface{}{
   712  				map[string]interface{}{
   713  					"beacon": crossref.NewLocalhost("City", berlin).String(),
   714  				},
   715  			},
   716  		},
   717  	})
   718  }
   719  
   720  func addTestDataCompanies(t *testing.T) {
   721  	var (
   722  		microsoft1 strfmt.UUID = "cfa3b21e-ca4f-4db7-a432-7fc6a23c534d"
   723  		microsoft2 strfmt.UUID = "8f75ed97-39dd-4294-bff7-ecabd7923062"
   724  		microsoft3 strfmt.UUID = "f343f51d-7e05-4084-bd66-d504db3b6bec"
   725  		apple1     strfmt.UUID = "477fec91-1292-4928-8f53-f0ff49c76900"
   726  		apple2     strfmt.UUID = "bb2cfdba-d4ba-4cf8-abda-e719ef35ac33"
   727  		apple3     strfmt.UUID = "b71d2b4c-3da1-4684-9c5e-aabd2a4f2998"
   728  		google1    strfmt.UUID = "8c2e21fc-46fe-4999-b41c-a800595129af"
   729  		google2    strfmt.UUID = "62b969c6-f184-4be0-8c40-7470af417cfc"
   730  		google3    strfmt.UUID = "c7829929-2037-4420-acbc-a433269feb93"
   731  	)
   732  
   733  	type companyTemplate struct {
   734  		id     strfmt.UUID
   735  		name   string
   736  		inCity []strfmt.UUID
   737  	}
   738  
   739  	companies := []companyTemplate{
   740  		{id: microsoft1, name: "Microsoft Inc.", inCity: []strfmt.UUID{dusseldorf}},
   741  		{id: microsoft2, name: "Microsoft Incorporated", inCity: []strfmt.UUID{dusseldorf, amsterdam}},
   742  		{id: microsoft3, name: "Microsoft", inCity: []strfmt.UUID{berlin}},
   743  		{id: apple1, name: "Apple Inc."},
   744  		{id: apple2, name: "Apple Incorporated"},
   745  		{id: apple3, name: "Apple"},
   746  		{id: google1, name: "Google Inc."},
   747  		{id: google2, name: "Google Incorporated"},
   748  		{id: google3, name: "Google"},
   749  	}
   750  
   751  	// companies
   752  	for _, company := range companies {
   753  		inCity := []interface{}{}
   754  		for _, c := range company.inCity {
   755  			inCity = append(inCity,
   756  				map[string]interface{}{
   757  					"beacon": crossref.NewLocalhost("City", c).String(),
   758  				})
   759  		}
   760  
   761  		createObject(t, &models.Object{
   762  			Class: "Company",
   763  			ID:    company.id,
   764  			Properties: map[string]interface{}{
   765  				"inCity": inCity,
   766  				"name":   company.name,
   767  			},
   768  		})
   769  	}
   770  
   771  	assertGetObjectEventually(t, companies[len(companies)-1].id)
   772  }
   773  
   774  func addTestDataPersons(t *testing.T) {
   775  	var (
   776  		alice strfmt.UUID = "5d0fa6ee-21c4-4b46-a735-f0208717837d"
   777  		bob   strfmt.UUID = "8615585a-2960-482d-b19d-8bee98ade52c"
   778  		john  strfmt.UUID = "3ef44474-b5e5-455d-91dc-d917b5b76165"
   779  		petra strfmt.UUID = "15d222c9-8c36-464b-bedb-113faa1c1e4c"
   780  	)
   781  
   782  	type personTemplate struct {
   783  		id         strfmt.UUID
   784  		name       string
   785  		livesIn    []strfmt.UUID
   786  		profession string
   787  		about      []string
   788  	}
   789  
   790  	persons := []personTemplate{
   791  		{
   792  			id: alice, name: "Alice", livesIn: []strfmt.UUID{}, profession: "Quality Control Analyst",
   793  			about: []string{"loves travelling very much"},
   794  		},
   795  		{
   796  			id: bob, name: "Bob", livesIn: []strfmt.UUID{amsterdam}, profession: "Mechanical Engineer",
   797  			about: []string{"loves travelling", "hates cooking"},
   798  		},
   799  		{
   800  			id: john, name: "John", livesIn: []strfmt.UUID{amsterdam, berlin}, profession: "Senior Mechanical Engineer",
   801  			about: []string{"hates swimming", "likes cooking", "loves travelling"},
   802  		},
   803  		{
   804  			id: petra, name: "Petra", livesIn: []strfmt.UUID{amsterdam, berlin, dusseldorf}, profession: "Quality Assurance Manager",
   805  			about: []string{"likes swimming", "likes cooking for family"},
   806  		},
   807  	}
   808  
   809  	// persons
   810  	for _, person := range persons {
   811  		livesIn := []interface{}{}
   812  		for _, c := range person.livesIn {
   813  			livesIn = append(livesIn,
   814  				map[string]interface{}{
   815  					"beacon": crossref.NewLocalhost("City", c).String(),
   816  				})
   817  		}
   818  
   819  		createObject(t, &models.Object{
   820  			Class: "Person",
   821  			ID:    person.id,
   822  			Properties: map[string]interface{}{
   823  				"livesIn":    livesIn,
   824  				"name":       person.name,
   825  				"profession": person.profession,
   826  				"about":      person.about,
   827  			},
   828  		})
   829  	}
   830  
   831  	assertGetObjectEventually(t, persons[len(persons)-1].id)
   832  }
   833  
   834  func addTestDataPizzas(t *testing.T) {
   835  	createObject(t, &models.Object{
   836  		Class: "Pizza",
   837  		ID:    quattroFormaggi,
   838  		Properties: map[string]interface{}{
   839  			"name":        "Quattro Formaggi",
   840  			"description": "Pizza quattro formaggi Italian: [ˈkwattro forˈmaddʒi] (four cheese pizza) is a variety of pizza in Italian cuisine that is topped with a combination of four kinds of cheese, usually melted together, with (rossa, red) or without (bianca, white) tomato sauce. It is popular worldwide, including in Italy,[1] and is one of the iconic items from pizzerias's menus.",
   841  		},
   842  	})
   843  	createObject(t, &models.Object{
   844  		Class: "Pizza",
   845  		ID:    fruttiDiMare,
   846  		Properties: map[string]interface{}{
   847  			"name":        "Frutti di Mare",
   848  			"description": "Frutti di Mare is an Italian type of pizza that may be served with scampi, mussels or squid. It typically lacks cheese, with the seafood being served atop a tomato sauce.",
   849  		},
   850  	})
   851  	createObject(t, &models.Object{
   852  		Class: "Pizza",
   853  		ID:    hawaii,
   854  		Properties: map[string]interface{}{
   855  			"name":        "Hawaii",
   856  			"description": "Universally accepted to be the best pizza ever created.",
   857  		},
   858  	})
   859  	createObject(t, &models.Object{
   860  		Class: "Pizza",
   861  		ID:    doener,
   862  		Properties: map[string]interface{}{
   863  			"name":        "Doener",
   864  			"description": "A innovation, some say revolution, in the pizza industry.",
   865  		},
   866  	})
   867  
   868  	assertGetObjectEventually(t, quattroFormaggi)
   869  	assertGetObjectEventually(t, fruttiDiMare)
   870  	assertGetObjectEventually(t, hawaii)
   871  	assertGetObjectEventually(t, doener)
   872  }
   873  
   874  func addTestDataCVC(t *testing.T) {
   875  	// add one object individually
   876  	createObject(t, &models.Object{
   877  		Class:  "CustomVectorClass",
   878  		ID:     cvc1,
   879  		Vector: []float32{1.1, 1.1, 1.1},
   880  		Properties: map[string]interface{}{
   881  			"name": "Ford",
   882  		},
   883  	})
   884  
   885  	assertGetObjectEventually(t, cvc1)
   886  
   887  	createObjectsBatch(t, []*models.Object{
   888  		{
   889  			Class:  "CustomVectorClass",
   890  			ID:     cvc2,
   891  			Vector: []float32{1.1, 1.1, 0.1},
   892  			Properties: map[string]interface{}{
   893  				"name": "Tesla",
   894  			},
   895  		},
   896  		{
   897  			Class:  "CustomVectorClass",
   898  			ID:     cvc3,
   899  			Vector: []float32{1.1, 0, 0},
   900  			Properties: map[string]interface{}{
   901  				"name": "Mercedes",
   902  			},
   903  		},
   904  	})
   905  	assertGetObjectEventually(t, cvc3)
   906  }
   907  
   908  func addTestDataNoProperties(t *testing.T) {
   909  	for _, object := range noPropsClassObjects() {
   910  		createObject(t, object)
   911  		assertGetObjectEventually(t, object.ID)
   912  	}
   913  }
   914  
   915  func addTestDataArrayClass(t *testing.T) {
   916  	for _, object := range arrayClassObjects() {
   917  		createObject(t, object)
   918  		assertGetObjectEventually(t, object.ID)
   919  	}
   920  }
   921  
   922  func addTestDataDuplicatesClass(t *testing.T) {
   923  	for _, object := range duplicatesClassObjects() {
   924  		createObject(t, object)
   925  		assertGetObjectEventually(t, object.ID)
   926  	}
   927  }
   928  
   929  func addTestDataRansomNotes(t *testing.T) {
   930  	const (
   931  		noteLengthMin = 4
   932  		noteLengthMax = 1024
   933  
   934  		batchSize  = 10
   935  		numBatches = 50
   936  	)
   937  
   938  	seededRand := rand.New(rand.NewSource(time.Now().UnixNano()))
   939  
   940  	for i := 0; i < numBatches; i++ {
   941  		batch := make([]*models.Object, batchSize)
   942  		for j := 0; j < batchSize; j++ {
   943  			noteLength := noteLengthMin + seededRand.Intn(noteLengthMax-noteLengthMin+1)
   944  			note := helper.GetRandomString(noteLength)
   945  
   946  			batch[j] = &models.Object{
   947  				Class:      "RansomNote",
   948  				Properties: map[string]interface{}{"contents": note},
   949  			}
   950  		}
   951  
   952  		createObjectsBatch(t, batch)
   953  	}
   954  }
   955  
   956  func addTestDataMultiShard(t *testing.T) {
   957  	for _, multiShard := range multishard.Objects() {
   958  		helper.CreateObject(t, multiShard)
   959  		helper.AssertGetObjectEventually(t, multiShard.Class, multiShard.ID)
   960  	}
   961  }
   962  
   963  func addTestDataNearObjectSearch(t *testing.T) {
   964  	classNames := []string{"NearObjectSearch", "NearObjectSearchShadow"}
   965  	ids := []strfmt.UUID{
   966  		"aa44bbee-ca5f-4db7-a412-5fc6a2300001",
   967  		"aa44bbee-ca5f-4db7-a412-5fc6a2300002",
   968  		"aa44bbee-ca5f-4db7-a412-5fc6a2300003",
   969  		"aa44bbee-ca5f-4db7-a412-5fc6a2300004",
   970  		"aa44bbee-ca5f-4db7-a412-5fc6a2300005",
   971  	}
   972  	names := []string{
   973  		"Mount Everest",
   974  		"Amsterdam is a cool city",
   975  		"Football is a game where people run after ball",
   976  		"Berlin is Germany's capital city",
   977  		"London is a cool city",
   978  	}
   979  
   980  	for _, className := range classNames {
   981  		createObjectClass(t, &models.Class{
   982  			Class: className,
   983  			ModuleConfig: map[string]interface{}{
   984  				"text2vec-contextionary": map[string]interface{}{
   985  					"vectorizeClassName": true,
   986  				},
   987  			},
   988  			Properties: []*models.Property{
   989  				{
   990  					Name:         "name",
   991  					DataType:     schema.DataTypeText.PropString(),
   992  					Tokenization: models.PropertyTokenizationWhitespace,
   993  				},
   994  			},
   995  		})
   996  	}
   997  
   998  	for i, id := range ids {
   999  		createObject(t, &models.Object{
  1000  			Class: classNames[0],
  1001  			ID:    id,
  1002  			Properties: map[string]interface{}{
  1003  				"name": names[i],
  1004  			},
  1005  		})
  1006  		assertGetObjectEventually(t, id)
  1007  		createObject(t, &models.Object{
  1008  			Class: classNames[1],
  1009  			ID:    id,
  1010  			Properties: map[string]interface{}{
  1011  				"name": fmt.Sprintf("altered contents of: %v", names[i]),
  1012  			},
  1013  		})
  1014  		assertGetObjectEventually(t, id)
  1015  	}
  1016  
  1017  	createObject(t, &models.Object{
  1018  		Class: classNames[0],
  1019  		ID:    "aa44bbee-ca5f-4db7-a412-5fc6a2300011",
  1020  		Properties: map[string]interface{}{
  1021  			"name": "the same content goes here just for explore tests",
  1022  		},
  1023  	})
  1024  	assertGetObjectEventually(t, "aa44bbee-ca5f-4db7-a412-5fc6a2300011")
  1025  	createObject(t, &models.Object{
  1026  		Class: classNames[1],
  1027  		ID:    "aa44bbee-ca5f-4db7-a412-5fc6a2300011",
  1028  		Properties: map[string]interface{}{
  1029  			"name": "the same content goes here just for explore tests",
  1030  		},
  1031  	})
  1032  	assertGetObjectEventually(t, "aa44bbee-ca5f-4db7-a412-5fc6a2300011")
  1033  }
  1034  
  1035  const (
  1036  	cursorClassID1 = strfmt.UUID("00000000-0000-0000-0000-000000000001")
  1037  	cursorClassID2 = strfmt.UUID("00000000-0000-0000-0000-000000000002")
  1038  	cursorClassID3 = strfmt.UUID("00000000-0000-0000-0000-000000000003")
  1039  	cursorClassID4 = strfmt.UUID("00000000-0000-0000-0000-000000000004")
  1040  	cursorClassID5 = strfmt.UUID("00000000-0000-0000-0000-000000000005")
  1041  	cursorClassID6 = strfmt.UUID("00000000-0000-0000-0000-000000000006")
  1042  	cursorClassID7 = strfmt.UUID("00000000-0000-0000-0000-000000000007")
  1043  )
  1044  
  1045  func addTestDataCursorSearch(t *testing.T) {
  1046  	className := "CursorClass"
  1047  	ids := []strfmt.UUID{
  1048  		cursorClassID1,
  1049  		cursorClassID2,
  1050  		cursorClassID3,
  1051  		cursorClassID4,
  1052  		cursorClassID5,
  1053  		cursorClassID6,
  1054  		cursorClassID7,
  1055  	}
  1056  	names := []string{
  1057  		"Mount Everest",
  1058  		"Amsterdam is a cool city",
  1059  		"Football is a game where people run after ball",
  1060  		"Berlin is Germany's capital city",
  1061  		"London is a cool city",
  1062  		"Wroclaw is a really cool city",
  1063  		"Brisbane is a city in Australia",
  1064  	}
  1065  
  1066  	createObjectClass(t, &models.Class{
  1067  		Class: className,
  1068  		ModuleConfig: map[string]interface{}{
  1069  			"text2vec-contextionary": map[string]interface{}{
  1070  				"vectorizeClassName": true,
  1071  			},
  1072  		},
  1073  		Properties: []*models.Property{
  1074  			{
  1075  				Name:         "name",
  1076  				DataType:     schema.DataTypeText.PropString(),
  1077  				Tokenization: models.PropertyTokenizationWhitespace,
  1078  			},
  1079  		},
  1080  	})
  1081  
  1082  	for i, id := range ids {
  1083  		createObject(t, &models.Object{
  1084  			Class: className,
  1085  			ID:    id,
  1086  			Properties: map[string]interface{}{
  1087  				"name": names[i],
  1088  			},
  1089  		})
  1090  		assertGetObjectEventually(t, id)
  1091  	}
  1092  }
  1093  
  1094  func addDateFieldClass(t *testing.T) {
  1095  	timestamps := []string{
  1096  		"2022-06-16T22:18:59.640162Z",
  1097  		"2022-06-16T22:19:01.495967Z",
  1098  		"2022-06-16T22:19:03.495596Z",
  1099  		"2022-06-16T22:19:04.3828349Z",
  1100  		"2022-06-16T22:19:05.894857Z",
  1101  		"2022-06-16T22:19:06.394958Z",
  1102  		"2022-06-16T22:19:07.589828Z",
  1103  		"2022-06-16T22:19:08.112395Z",
  1104  		"2022-06-16T22:19:10.339493Z",
  1105  		"2022-06-16T22:19:11.837473Z",
  1106  	}
  1107  
  1108  	for i := 0; i < len(timestamps); i++ {
  1109  		createObject(t, &models.Object{
  1110  			Class: "HasDateField",
  1111  			Properties: map[string]interface{}{
  1112  				"unique":    fmt.Sprintf("#%d", i+1),
  1113  				"timestamp": timestamps[i],
  1114  				"identical": "hello!",
  1115  			},
  1116  		})
  1117  	}
  1118  }
  1119  
  1120  func mustParseYear(year string) time.Time {
  1121  	date := fmt.Sprintf("%s-01-01T00:00:00+02:00", year)
  1122  	asTime, err := time.Parse(time.RFC3339, date)
  1123  	if err != nil {
  1124  		panic(err)
  1125  	}
  1126  	return asTime
  1127  }