diff --git a/.editorconfig b/.editorconfig
index a11278d02b..59ff02b4bd 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -13,7 +13,12 @@ insert_final_newline = true
quote_type = single
[*.{js,py}]
+indent_style = space
indent_size = 4
+[*.{go}]
+indent_style = tab
+indent_size = 2
+
[*.{md,txt}]
trim_trailing_whitespace = false
diff --git a/.gitignore b/.gitignore
index 81bf5a9cb9..b499d9287a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,8 @@
.venv
nohup.out
tests/temp.*
+_includes/code/howto/java/target
+_includes/code/howto/go/vendor
**/.ipynb
**/.ipynb_checkpoints/*
diff --git a/_includes/code/howto/go/docs/helper/envhelper.go b/_includes/code/howto/go/docs/helper/envhelper.go
new file mode 100644
index 0000000000..9c7565b3b6
--- /dev/null
+++ b/_includes/code/howto/go/docs/helper/envhelper.go
@@ -0,0 +1,28 @@
+package helper
+
+import "os"
+
+const (
+ envScheme = "WEAVIATE_SCHEME"
+ envHost = "WEAVIATE_HOST"
+ envPort = "WEAVIATE_PORT"
+)
+
+func EnvScheme(defaultScheme string) string {
+ return Env(envScheme, defaultScheme)
+}
+
+func EnvHost(defaulHost string) string {
+ return Env(envHost, defaulHost)
+}
+
+func EnvPort(defaultPort string) string {
+ return Env(envPort, defaultPort)
+}
+
+func Env(envName string, def string) string {
+ if env := os.Getenv(envName); env != "" {
+ return env
+ }
+ return def
+}
diff --git a/_includes/code/howto/go/docs/manage-data.classes_test.go b/_includes/code/howto/go/docs/manage-data.classes_test.go
new file mode 100644
index 0000000000..3d6fd070e1
--- /dev/null
+++ b/_includes/code/howto/go/docs/manage-data.classes_test.go
@@ -0,0 +1,125 @@
+// How-to: Manage-Data -> Classes
+package docs
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+ "github.com/weaviate/weaviate-go-client/v4/weaviate"
+ "github.com/weaviate/weaviate/entities/models"
+ "github.com/weaviate/weaviate/entities/vectorindex/hnsw"
+ "weaviate.io/docs/docs/helper"
+)
+
+func Test_ManageDataClasses(t *testing.T) {
+ ctx := context.Background()
+ scheme := helper.EnvScheme("http")
+ host := helper.EnvHost("localhost")
+ port := helper.EnvPort("8080")
+
+ config := weaviate.Config{Scheme: scheme, Host: host + ":" + port}
+ client, err := weaviate.NewClient(config)
+ require.NoError(t, err)
+
+ err = client.Schema().AllDeleter().Do(ctx)
+ require.NoError(t, err)
+
+ // START CreateClass // START ReadOneClass // START UpdateClass
+ className := "Article"
+
+ // END CreateClass // END ReadOneClass // END UpdateClass
+
+ t.Run("create class", func(t *testing.T) {
+ // START CreateClass
+ emptyClass := &models.Class{
+ Class: className,
+ }
+
+ // Add the class to the schema
+ err := client.Schema().ClassCreator().
+ WithClass(emptyClass).
+ Do(ctx)
+
+ // END CreateClass
+
+ require.NoError(t, err)
+ })
+
+ t.Run("read one class", func(t *testing.T) {
+ // START ReadOneClass
+ class, err := client.Schema().ClassGetter().
+ WithClassName(className).
+ Do(ctx)
+
+ // END ReadOneClass
+
+ require.NoError(t, err)
+
+ // START ReadOneClass
+ b, err := json.MarshalIndent(class, "", " ")
+ // END ReadOneClass
+ require.NoError(t, err)
+ // START ReadOneClass
+ fmt.Println(string(b))
+ // END ReadOneClass
+ })
+
+ t.Run("read all classes", func(t *testing.T) {
+ // START ReadAllClasses
+ schema, err := client.Schema().Getter().
+ Do(ctx)
+
+ // END ReadAllClasses
+
+ require.NoError(t, err)
+
+ // START ReadAllClasses
+ b, err := json.MarshalIndent(schema, "", " ")
+ // END ReadAllClasses
+ require.NoError(t, err)
+ // START ReadAllClasses
+ fmt.Println(string(b))
+ // END ReadAllClasses
+ })
+
+ t.Run("update class", func(t *testing.T) {
+ errDel := client.Schema().ClassDeleter().WithClassName(className).Do(ctx)
+ require.NoError(t, errDel)
+
+ // START UpdateClassTODO
+ // Define class
+ originalClass := &models.Class{
+ Class: className,
+ VectorIndexConfig: map[string]interface{}{
+ "distance": hnsw.DistanceCosine, // Note the distance metric
+ },
+ }
+
+ // Add the class to the schema
+ err := client.Schema().ClassCreator().
+ WithClass(originalClass).
+ Do(ctx)
+
+ // END UpdateClassTODO
+
+ require.NoError(t, err)
+
+ // START UpdateClassTODO
+ // Define updated class
+ updatedClass := &models.Class{
+ Class: className,
+ VectorIndexConfig: map[string]interface{}{
+ "distance": hnsw.DistanceDot, // Note the distance metric
+ },
+ }
+
+ // Update the class definition
+ _ = updatedClass
+ // TODO Not yet available in GO
+
+ // END UpdateClassTODO
+ })
+}
diff --git a/_includes/code/howto/go/docs/manage-data.create_test.go b/_includes/code/howto/go/docs/manage-data.create_test.go
new file mode 100644
index 0000000000..5d877f2c22
--- /dev/null
+++ b/_includes/code/howto/go/docs/manage-data.create_test.go
@@ -0,0 +1,170 @@
+// How-to: Manage-data -> Create objects
+package docs
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "github.com/weaviate/weaviate-go-client/v4/weaviate"
+ "github.com/weaviate/weaviate/entities/models"
+ "github.com/weaviate/weaviate/entities/schema"
+ "weaviate.io/docs/docs/helper"
+)
+
+func Test_ManageDataCreate(t *testing.T) {
+ ctx := context.Background()
+ scheme := helper.EnvScheme("http")
+ host := helper.EnvHost("localhost")
+ port := helper.EnvPort("8080")
+ openaiApiKey := helper.Env("OPENAI_APIKEY", "_dummy_")
+
+ config := weaviate.Config{Scheme: scheme, Host: host + ":" + port, Headers: map[string]string{
+ "X-Openai-Api-Key": openaiApiKey,
+ }}
+ client, err := weaviate.NewClient(config)
+ require.NoError(t, err)
+
+ err = client.Schema().AllDeleter().Do(ctx)
+ require.NoError(t, err)
+
+ className := "JeopardyQuestion"
+
+ t.Run("create class", func(t *testing.T) {
+ jeopardyClass := &models.Class{
+ Class: className,
+ Description: "A Jeopardy! question",
+ Vectorizer: "text2vec-openai",
+ Properties: []*models.Property{
+ {
+ Name: "question",
+ DataType: schema.DataTypeText.PropString(),
+ },
+ {
+ Name: "answer",
+ DataType: schema.DataTypeText.PropString(),
+ },
+ },
+ }
+
+ err := client.Schema().ClassCreator().
+ WithClass(jeopardyClass).
+ Do(ctx)
+
+ require.NoError(t, err)
+ })
+
+ t.Run("create object", func(t *testing.T) {
+ // CreateObject START
+ w, err := client.Data().Creator().
+ WithClassName("JeopardyQuestion").
+ WithProperties(map[string]interface{}{
+ "question": "This vector DB is OSS and supports automatic property type inference on import",
+ // "answer": "Weaviate", // schema properties can be omitted
+ "somePropNotInTheSchema": 123, // will be automatically added as a number property
+ }).
+ Do(ctx)
+
+ // CreateObject END
+
+ require.NoError(t, err)
+
+ // CreateObject START
+ // the returned value is a wrapped object
+ b, err := json.MarshalIndent(w.Object, "", " ")
+ // CreateObject END
+ require.NoError(t, err)
+ // CreateObject START
+ fmt.Println(string(b))
+ // CreateObject END
+ })
+
+ t.Run("create object with id and vector", func(t *testing.T) {
+ // CreateObjectWithIdAndVector START
+ vector := make([]float32, 1536)
+ for i := 0; i < len(vector); i++ {
+ vector[i] = 0.12345
+ }
+
+ w, err := client.Data().Creator().
+ WithClassName("JeopardyQuestion").
+ WithProperties(map[string]interface{}{
+ "question": "This vector DB is OSS and supports automatic property type inference on import",
+ "answer": "Weaviate",
+ }).
+ // highlight-start
+ WithID("12345678-e64f-5d94-90db-c8cfa3fc1234").
+ WithVector(vector).
+ // highlight-end
+ Do(ctx)
+
+ // CreateObjectWithIdAndVector END
+
+ require.NoError(t, err)
+
+ // CreateObjectWithIdAndVector START
+ // the returned value is a wrapped object
+ b, err := json.MarshalIndent(w.Object, "", " ")
+ // CreateObjectWithIdAndVector END
+ require.NoError(t, err)
+ // CreateObjectWithIdAndVector START
+ fmt.Println(string(b))
+ // CreateObjectWithIdAndVector END
+ })
+
+ t.Run("create object with deterministic id", func(t *testing.T) {
+ // CreateObjectWithDeterministicIdTODO START
+ properties := map[string]interface{}{
+ "question": "This vector DB is OSS and supports automatic property type inference on import",
+ "answer": "Weaviate",
+ }
+
+ // highlight-start
+ // String id = "gen_uuid5(properties)"; // TODO implement
+ id := "17f91943-1a5e-46d3-9323-a1cdb735591c"
+ // highlight-end
+
+ w, err := client.Data().Creator().
+ WithClassName("JeopardyQuestion").
+ WithProperties(properties).
+ WithID(id).
+ Do(ctx)
+
+ // CreateObjectWithDeterministicIdTODO END
+
+ require.NoError(t, err)
+
+ // CreateObjectWithDeterministicIdTODO START
+ // the returned value is a wrapped object
+ b, err := json.MarshalIndent(w.Object, "", " ")
+ // CreateObjectWithDeterministicIdTODO END
+ require.NoError(t, err)
+ // CreateObjectWithDeterministicIdTODO START
+ fmt.Println(string(b))
+ // CreateObjectWithDeterministicIdTODO END
+ })
+
+ t.Run("validate object", func(t *testing.T) {
+ // ValidateObject START
+ err := client.Data().Validator().
+ WithClassName("JeopardyQuestion").
+ WithProperties(map[string]interface{}{
+ "question": "This vector DB is OSS and supports automatic property type inference on import",
+ "answer": "Weaviate",
+ "thisPropShouldNotEndUpInTheSchema": -1,
+ }).
+ WithID("12345678-1234-1234-1234-123456789012").
+ Do(ctx)
+
+ // ValidateObject END
+
+ require.Error(t, err)
+
+ // ValidateObject START
+ assert.ErrorContains(t, err, "invalid object: no such prop with name 'thisPropShouldNotEndUpInTheSchema' found")
+ // ValidateObject END
+ })
+}
diff --git a/_includes/code/howto/go/docs/manage-data.cross-refs_test.go b/_includes/code/howto/go/docs/manage-data.cross-refs_test.go
new file mode 100644
index 0000000000..2e21f28d05
--- /dev/null
+++ b/_includes/code/howto/go/docs/manage-data.cross-refs_test.go
@@ -0,0 +1,243 @@
+// How-to: Manage-data -> (Batch) Import items
+
+// TODO - review tests
+package docs
+
+import (
+ "context"
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "github.com/weaviate/weaviate-go-client/v4/weaviate"
+ "github.com/weaviate/weaviate/entities/models"
+)
+
+func Test_ManageDataCrossRefs(t *testing.T) {
+ ctx := context.Background()
+ scheme := "http"
+ host := "localhost:8080"
+
+ config := weaviate.Config{Scheme: scheme, Host: host}
+ client, err := weaviate.NewClient(config)
+ require.NoError(t, err)
+
+ delProps := func(uuid, className string, propNames ...string) (bool, error) {
+ objs, err := client.Data().ObjectsGetter().WithID(uuid).WithClassName(className).Do(ctx)
+ if err != nil {
+ return false, err
+ }
+ if objs == nil || len(objs) == 0 {
+ return false, fmt.Errorf("object with id: %v not found", uuid)
+ }
+ if objs[0].Properties == nil {
+ return false, fmt.Errorf("object with id: %v has no properties", uuid)
+ }
+ properties := objs[0].Properties.(map[string]interface{})
+ for _, propName := range propNames {
+ delete(properties, propName)
+ }
+ err = client.Data().Updater().
+ WithID(uuid).
+ WithClassName(className).
+ WithProperties(properties).
+ Do(ctx)
+ return err == nil, err
+ }
+
+ assertCrossRefHref := func(t *testing.T, objs []*models.Object, propName string, hrefs ...string) {
+ require.Len(t, objs, 1)
+ for i := range objs {
+ hasCategory := objs[i].Properties.(map[string]interface{})[propName]
+ require.NotNil(t, hasCategory)
+ hrefValue := hasCategory.([]interface{})[0].(map[string]interface{})["href"]
+ for _, href := range hrefs {
+ assert.Equal(t, href, hrefValue)
+ }
+ }
+ }
+
+ // sfID := "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
+ // usCitiesID := "20ffc68d-986b-5e71-a680-228dba18d7ef"
+ // museumsID := "fec50326-dfa1-53c9-90e8-63d0240bd933"
+
+ t.Run("Add one-way cross-ref", func(t *testing.T) {
+ // OneWay Go
+ sfID := "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
+ usCitiesID := "20ffc68d-986b-5e71-a680-228dba18d7ef"
+
+ client.Data().ReferenceCreator().
+ WithClassName("JeopardyQuestion").
+ WithID(sfID).
+ WithReferenceProperty("hasCategory").
+ WithReference(client.Data().ReferencePayloadBuilder().
+ WithClassName("JeopardyCategory").
+ WithID(usCitiesID).
+ Payload()).
+ Do(ctx)
+ // END OneWay Go
+
+ objs, err := client.Data().ObjectsGetter().
+ WithClassName("JeopardyQuestion").
+ WithID(sfID).
+ Do(ctx)
+ require.NoError(t, err)
+ assertCrossRefHref(t, objs, "hasCategory", fmt.Sprintf("http://localhost:8080/v1/objects/JeopardyCategory/%v", usCitiesID))
+ })
+
+ t.Run("Add bidirectional cross-ref", func(t *testing.T) {
+ // TwoWay Go
+ sfID := "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
+ usCitiesID := "20ffc68d-986b-5e71-a680-228dba18d7ef"
+
+ // END TwoWay Go
+
+ isDeleted, err := delProps(sfID, "JeopardyQuestion", "hasCategory")
+ require.NoError(t, err)
+ require.True(t, isDeleted)
+ isDeleted, err = delProps(sfID, "JeopardyCategory", "hasQuestion")
+ require.NoError(t, err)
+ require.True(t, isDeleted)
+
+ // TwoWay Go
+ // First, add the "hasQuestion" cross-reference property to the JeopardyCategory class
+ client.Schema().PropertyCreator().
+ WithClassName("JeopardyCategory").
+ WithProperty(&models.Property{
+ Name: "hasQuestion",
+ DataType: []string{"JeopardyQuestion"},
+ }).
+ Do(ctx)
+
+ // For the "San Francisco" JeopardyQuestion object, add a cross-reference to the "U.S. CITIES" JeopardyCategory object
+ client.Data().ReferenceCreator().
+ WithClassName("JeopardyQuestion").
+ WithID(sfID).
+ WithReferenceProperty("hasCategory").
+ WithReference(client.Data().ReferencePayloadBuilder().
+ WithClassName("JeopardyCategory").
+ WithID(usCitiesID).
+ Payload()).
+ Do(ctx)
+
+ // For the "U.S. CITIES" JeopardyCategory object, add a cross-reference to "San Francisco"
+ client.Data().ReferenceCreator().
+ WithClassName("JeopardyCategory").
+ WithID(usCitiesID).
+ WithReferenceProperty("hasQuestion").
+ WithReference(client.Data().ReferencePayloadBuilder().
+ WithClassName("JeopardyQuestion").
+ WithID(sfID).
+ Payload()).
+ Do(ctx)
+ // END TwoWay Go
+
+ sf, err := client.Data().ObjectsGetter().
+ WithClassName("JeopardyQuestion").
+ WithID(sfID).
+ Do(ctx)
+ require.NoError(t, err)
+ assertCrossRefHref(t, sf, "hasCategory", fmt.Sprintf("http://localhost:8080/v1/objects/JeopardyCategory/%v", usCitiesID))
+
+ usCities, err := client.Data().ObjectsGetter().
+ WithClassName("JeopardyCategory").
+ WithID(usCitiesID).
+ Do(ctx)
+ require.NoError(t, err)
+ assertCrossRefHref(t, usCities, "hasQuestion", fmt.Sprintf("http://localhost:8080/v1/objects/JeopardyQuestion/%v", sfID))
+ })
+
+ t.Run("Add multiple cross-refs", func(t *testing.T) {
+ // Multiple Go
+ sfID := "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
+ usCitiesID := "20ffc68d-986b-5e71-a680-228dba18d7ef"
+ museumsID := "fec50326-dfa1-53c9-90e8-63d0240bd933"
+
+ // Add to "San Francisco" the "U.S. CITIES" category
+ client.Data().ReferenceCreator().
+ WithClassName("JeopardyQuestion").
+ WithID(sfID).
+ WithReferenceProperty("hasCategory").
+ WithReference(client.Data().ReferencePayloadBuilder().
+ WithClassName("JeopardyCategory").
+ WithID(usCitiesID).
+ Payload()).
+ Do(ctx)
+
+ // Add the "MUSEUMS" category as well
+ client.Data().ReferenceCreator().
+ WithClassName("JeopardyQuestion").
+ WithID(sfID).
+ WithReferenceProperty("hasCategory").
+ WithReference(client.Data().ReferencePayloadBuilder().
+ WithClassName("JeopardyCategory").
+ WithID(museumsID).
+ Payload()).
+ Do(ctx)
+ // END Multiple Go
+
+ sf, err := client.Data().ObjectsGetter().
+ WithClassName("JeopardyQuestion").
+ WithID(sfID).
+ Do(ctx)
+ require.NoError(t, err)
+ assertCrossRefHref(t, sf, "hasCategory",
+ fmt.Sprintf("http://localhost:8080/v1/objects/JeopardyCategory/%v", usCitiesID),
+ fmt.Sprintf("http://localhost:8080/v1/objects/JeopardyCategory/%v", museumsID),
+ )
+ })
+
+ t.Run("Delete cross-refs", func(t *testing.T) {
+ // Delete Go
+ sfID := "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
+ museumsID := "fec50326-dfa1-53c9-90e8-63d0240bd933"
+
+ // From the "San Francisco" JeopardyQuestion object, delete the "MUSEUMS" category cross-reference
+ client.Data().ReferenceDeleter().
+ WithClassName("JeopardyQuestion").
+ WithID(sfID).
+ WithReferenceProperty("hasCategory").
+ WithReference(client.Data().ReferencePayloadBuilder().
+ WithClassName("JeopardyCategory").
+ WithID(museumsID).
+ Payload()).
+ Do(ctx)
+ // END Delete Go
+
+ usCitiesID := "20ffc68d-986b-5e71-a680-228dba18d7ef"
+ sf, err := client.Data().ObjectsGetter().
+ WithClassName("JeopardyQuestion").
+ WithID(sfID).
+ Do(ctx)
+ require.NoError(t, err)
+ assertCrossRefHref(t, sf, "hasCategory", fmt.Sprintf("http://localhost:8080/v1/objects/JeopardyCategory/%v", usCitiesID))
+ })
+
+ t.Run("Update cross-refs", func(t *testing.T) {
+ // Update Go
+ sfID := "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
+ museumsID := "fec50326-dfa1-53c9-90e8-63d0240bd933"
+
+ // In the "San Francisco" JeopardyQuestion object, set the "hasCategory" cross-reference only to "MUSEUMS"
+ client.Data().ReferenceReplacer().
+ WithClassName("JeopardyQuestion").
+ WithID(sfID).
+ WithReferenceProperty("hasCategory").
+ WithReferences(&models.MultipleRef{
+ client.Data().ReferencePayloadBuilder().
+ WithClassName("JeopardyCategory").
+ WithID(museumsID).
+ Payload(),
+ }).
+ Do(ctx)
+ // END Update Go
+
+ sf, err := client.Data().ObjectsGetter().
+ WithClassName("JeopardyQuestion").
+ WithID(sfID).
+ Do(ctx)
+ require.NoError(t, err)
+ assertCrossRefHref(t, sf, "hasCategory", fmt.Sprintf("http://localhost:8080/v1/objects/JeopardyCategory/%v", museumsID))
+ })
+}
diff --git a/_includes/code/howto/go/docs/manage-data.delete_test.go b/_includes/code/howto/go/docs/manage-data.delete_test.go
new file mode 100644
index 0000000000..bad5ab43ae
--- /dev/null
+++ b/_includes/code/howto/go/docs/manage-data.delete_test.go
@@ -0,0 +1,123 @@
+// How-to: Manage-data -> Create objects
+package docs
+
+import (
+ "context"
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "github.com/weaviate/weaviate-go-client/v4/weaviate"
+ "github.com/weaviate/weaviate-go-client/v4/weaviate/filters"
+ "weaviate.io/docs/docs/helper"
+)
+
+func Test_ManageDataDelete(t *testing.T) {
+ ctx := context.Background()
+ scheme := helper.EnvScheme("http")
+ host := helper.EnvHost("localhost")
+ port := helper.EnvPort("8080")
+ openaiApiKey := helper.Env("OPENAI_APIKEY", "_dummy_")
+
+ config := weaviate.Config{Scheme: scheme, Host: host + ":" + port, Headers: map[string]string{
+ "X-Openai-Api-Key": openaiApiKey,
+ }}
+ client, err := weaviate.NewClient(config)
+ require.NoError(t, err)
+
+ err = client.Schema().AllDeleter().Do(ctx)
+ require.NoError(t, err)
+
+ className := "EphemeralObject"
+
+ t.Run("Delete object", func(t *testing.T) {
+ // START DeleteObject
+ idToDelete := "..." // replace with the id of the object you want to delete
+
+ // END DeleteObject
+ _ = idToDelete
+
+ result, err := client.Data().Creator().
+ WithClassName(className).
+ WithProperties(map[string]interface{}{
+ "name": "EphemeralObjectA",
+ }).
+ Do(ctx)
+ require.NoError(t, err)
+ require.NotNil(t, result)
+ idToDelete = result.Object.ID.String()
+
+ // START DeleteObject
+ client.Data().Deleter().
+ WithClassName("EphemeralObject").
+ WithID(idToDelete).
+ Do(ctx)
+ // END DeleteObject
+
+ exists, err := client.Data().Checker().WithClassName(className).WithID(idToDelete).Do(ctx)
+ require.NoError(t, err)
+ assert.False(t, exists)
+ })
+
+ t.Run("Dry run", func(t *testing.T) {
+ for i := 0; i < 5; i++ {
+ obj, err := client.Data().Creator().
+ WithClassName(className).
+ WithProperties(map[string]interface{}{
+ "name": fmt.Sprintf("EphemeralObject%v", i),
+ }).
+ Do(ctx)
+ require.NoError(t, err)
+ require.NotNil(t, obj)
+ }
+
+ // START DryRun
+ response, err := client.Batch().ObjectsBatchDeleter().
+ WithClassName("EphemeralObject").
+ // Same `where` filter as in the GraphQL API
+ WithWhere(filters.Where().
+ WithPath([]string{"name"}).
+ WithOperator(filters.Like).
+ WithValueText("EphemeralObject*")).
+ // highlight-start
+ WithDryRun(true).
+ WithOutput("verbose").
+ // highlight-end
+ Do(ctx)
+ if err != nil {
+ // handle error
+ panic(err)
+ }
+
+ fmt.Printf("%+v\n", *response)
+ // END DryRun
+ assert.Equal(t, int64(5), response.Results.Matches)
+ })
+
+ t.Run("Batch delete", func(t *testing.T) {
+ // START DeleteBatch
+ response, err := client.Batch().ObjectsBatchDeleter().
+ WithClassName("EphemeralObject").
+ WithOutput("minimal").
+ // highlight-start
+ // Same `where` filter as in the GraphQL API
+ WithWhere(filters.Where().
+ WithPath([]string{"name"}).
+ WithOperator(filters.Like).
+ WithValueText("EphemeralObject*")).
+ // highlight-end
+ Do(ctx)
+ if err != nil {
+ // handle error
+ panic(err)
+ }
+
+ fmt.Printf("%+v\n", *response)
+ // END DeleteBatch
+ assert.Equal(t, int64(5), response.Results.Matches)
+ objects, err := client.Data().ObjectsGetter().WithClassName(className).Do(ctx)
+ require.NoError(t, err)
+ assert.Len(t, objects, 0)
+ })
+}
diff --git a/_includes/code/howto/go/docs/manage-data.import_test.go b/_includes/code/howto/go/docs/manage-data.import_test.go
new file mode 100644
index 0000000000..57ac205c1f
--- /dev/null
+++ b/_includes/code/howto/go/docs/manage-data.import_test.go
@@ -0,0 +1,191 @@
+// How-to: Manage-data -> (Batch) Import items
+package docs
+
+import (
+ "context"
+ "crypto/md5"
+ "fmt"
+ "strings"
+ "testing"
+
+ "github.com/go-openapi/strfmt"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "github.com/weaviate/weaviate-go-client/v4/weaviate"
+ "github.com/weaviate/weaviate-go-client/v4/weaviate/graphql"
+ "github.com/weaviate/weaviate/entities/models"
+ "weaviate.io/docs/docs/helper"
+)
+
+func Test_ManageDataImport(t *testing.T) {
+ ctx := context.Background()
+ scheme := helper.EnvScheme("http")
+ host := helper.EnvHost("localhost")
+ port := helper.EnvPort("8080")
+ openaiApiKey := helper.Env("OPENAI_APIKEY", "_dummy_")
+
+ config := weaviate.Config{Scheme: scheme, Host: host + ":" + port, Headers: map[string]string{
+ "X-Openai-Api-Key": openaiApiKey,
+ }}
+ client, err := weaviate.NewClient(config)
+ require.NoError(t, err)
+
+ err = client.Schema().AllDeleter().Do(ctx)
+ require.NoError(t, err)
+
+ checkNumberOfResults := func(t *testing.T, className string) {
+ resp, err := client.GraphQL().Aggregate().WithClassName(className).WithFields(graphql.Field{Name: "meta{count}"}).Do(ctx)
+ require.NoError(t, err)
+ require.Empty(t, resp.Errors)
+ agg := resp.Data["Aggregate"].(map[string]interface{})
+ objects := agg[className].([]interface{})
+ require.Len(t, objects, 1)
+ meta := objects[0].(map[string]interface{})["meta"].(map[string]interface{})
+ assert.Equal(t, float64(5), meta["count"])
+ }
+
+ deleteClass := func(t *testing.T, className string) {
+ err = client.Schema().ClassDeleter().WithClassName(className).Do(ctx)
+ require.NoError(t, err)
+ }
+
+ t.Run("Basic Batch Import", func(t *testing.T) {
+ ctx := context.Background()
+ // BasicBatchImportExample
+ className := "YourClassName" // Replace with your class name
+ dataObjs := []models.PropertySchema{}
+ for i := 0; i < 5; i++ {
+ dataObjs = append(dataObjs, map[string]interface{}{
+ "title": fmt.Sprintf("Object %v", i), // Replace with your actual objects
+ })
+ }
+
+ // highlight-start
+ batcher := client.Batch().ObjectsBatcher()
+ for _, dataObj := range dataObjs {
+ batcher.WithObjects(&models.Object{
+ Class: className,
+ Properties: dataObj,
+ // Tenant: "tenantA", // If multi-tenancy is enabled, specify the tenant to which the object will be added.
+ })
+ }
+
+ // Flush
+ batcher.Do(ctx)
+ // highlight-end
+ // END BasicBatchImportExample
+
+ checkNumberOfResults(t, className)
+ deleteClass(t, className)
+ })
+
+ t.Run("Batch import with custom ID", func(t *testing.T) {
+ ctx := context.Background()
+ // BatchImportWithIDExample
+ // highlight-start
+ generateUUID := func(input string) strfmt.UUID {
+ input = strings.ToLower(input)
+ hash := md5.Sum([]byte(input))
+ uuid := fmt.Sprintf("%x-%x-%x-%x-%x", hash[0:4], hash[4:6], hash[6:8], hash[8:10], hash[10:])
+ return strfmt.UUID(uuid)
+ }
+ // highlight-end
+
+ className := "YourClassName" // Replace with your class name
+ dataObjs := []models.PropertySchema{}
+ for i := 0; i < 5; i++ {
+ dataObjs = append(dataObjs, map[string]interface{}{
+ "title": fmt.Sprintf("Object %v", i), // Replace with your actual objects
+ })
+ }
+
+ // highlight-start
+ batcher := client.Batch().ObjectsBatcher()
+ for _, dataObj := range dataObjs {
+ batcher.WithObjects(&models.Object{
+ Class: className,
+ Properties: dataObj,
+ // highlight-start
+ ID: generateUUID((dataObj.(map[string]interface{}))["title"].(string)),
+ // highlight-end
+ })
+ }
+
+ // Flush
+ batcher.Do(ctx)
+ // END BatchImportWithIDExample
+
+ checkNumberOfResults(t, className)
+
+ resp, err := client.GraphQL().Get().
+ WithClassName(className).
+ WithFields(graphql.Field{Name: "title"}, graphql.Field{Name: "_additional{id vector}"}).
+ Do(ctx)
+ require.NoError(t, err)
+ require.Empty(t, resp.Errors)
+ get := resp.Data["Get"].(map[string]interface{})
+ objects := get[className].([]interface{})
+ require.Len(t, objects, 5)
+ for _, obj := range objects {
+ id := obj.(map[string]interface{})["_additional"].(map[string]interface{})["id"].(string)
+ v, ok := obj.(map[string]interface{})["_additional"].(map[string]interface{})["vector"].([]interface{})
+ fmt.Printf("vector: %T ok: %v\n", v[0], ok)
+ title := obj.(map[string]interface{})["title"].(string)
+ assert.Equal(t, id, generateUUID(title).String())
+ }
+
+ deleteClass(t, className)
+ })
+
+ t.Run("Batch import with custom vector", func(t *testing.T) {
+ // BatchImportWithVectorExample
+ className := "YourClassName" // Replace with your class name
+ dataObjs := []models.PropertySchema{}
+ for i := 0; i < 5; i++ {
+ dataObjs = append(dataObjs, map[string]interface{}{
+ "title": fmt.Sprintf("Object %v", i), // Replace with your actual objects
+ })
+ }
+ vectors := [][]float32{}
+ for i := 0; i < 5; i++ {
+ vector := make([]float32, 10)
+ for j := range vector {
+ vector[j] = 0.25 + float32(j/100) // Replace with your actual vectors
+ }
+ vectors = append(vectors, vector)
+ }
+
+ // highlight-start
+ batcher := client.Batch().ObjectsBatcher()
+ for i, dataObj := range dataObjs {
+ batcher.WithObjects(&models.Object{
+ Class: className,
+ Properties: dataObj,
+ // highlight-start
+ Vector: vectors[i],
+ // highlight-end
+ })
+ }
+
+ // Flush
+ batcher.Do(ctx)
+ // END BatchImportWithVectorExample
+
+ checkNumberOfResults(t, className)
+ resp, err := client.GraphQL().Get().
+ WithClassName(className).
+ WithFields(graphql.Field{Name: "_additional{vector}"}).
+ Do(ctx)
+ require.NoError(t, err)
+ require.Empty(t, resp.Errors)
+ agg := resp.Data["Get"].(map[string]interface{})
+ objects := agg[className].([]interface{})
+ require.Len(t, objects, 5)
+ for _, obj := range objects {
+ vector := obj.(map[string]interface{})["_additional"].(map[string]interface{})["vector"].([]interface{})
+ assert.GreaterOrEqual(t, vector[0], 0.25)
+ assert.LessOrEqual(t, vector[9], 0.3)
+ }
+ deleteClass(t, className)
+ })
+}
diff --git a/_includes/code/howto/go/docs/manage-data.multi-tenancy_test.go b/_includes/code/howto/go/docs/manage-data.multi-tenancy_test.go
new file mode 100644
index 0000000000..532bd13dc9
--- /dev/null
+++ b/_includes/code/howto/go/docs/manage-data.multi-tenancy_test.go
@@ -0,0 +1,181 @@
+// How-to: Manage-data -> Create objects
+package docs
+
+import (
+ "context"
+ "fmt"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "github.com/weaviate/weaviate-go-client/v4/weaviate"
+ "github.com/weaviate/weaviate-go-client/v4/weaviate/graphql"
+ "github.com/weaviate/weaviate/entities/models"
+ "weaviate.io/docs/docs/helper"
+)
+
+func Test_ManageDataMultiTenancy(t *testing.T) {
+ ctx := context.Background()
+ scheme := helper.EnvScheme("http")
+ host := helper.EnvHost("localhost")
+ port := helper.EnvPort("8080")
+ openaiApiKey := helper.Env("OPENAI_APIKEY", "_dummy_")
+
+ config := weaviate.Config{Scheme: scheme, Host: host + ":" + port, Headers: map[string]string{
+ "X-Openai-Api-Key": openaiApiKey,
+ }}
+ client, err := weaviate.NewClient(config)
+ require.NoError(t, err)
+
+ err = client.Schema().AllDeleter().Do(ctx)
+ require.NoError(t, err)
+
+ className := "MultiTenancyClass"
+
+ t.Run("Add tenants to class", func(t *testing.T) {
+ // START AddTenantsToClass
+ client.Schema().ClassCreator().
+ WithClass(&models.Class{
+ Class: "MultiTenancyClass",
+ MultiTenancyConfig: &models.MultiTenancyConfig{
+ Enabled: true,
+ },
+ }).
+ Do(ctx)
+
+ client.Schema().TenantsCreator().
+ WithClassName("MultiTenancyClass").
+ WithTenants(models.Tenant{Name: "tenantA"}, models.Tenant{Name: "tenantB"}).
+ Do(ctx)
+ // END AddTenantsToClass
+
+ tenants, err := client.Schema().TenantsGetter().WithClassName(className).Do(ctx)
+ require.NoError(t, err)
+ require.Len(t, tenants, 2)
+
+ class, err := client.Schema().ClassGetter().WithClassName(className).Do(ctx)
+ require.NoError(t, err)
+ require.NotNil(t, class)
+ assert.True(t, class.MultiTenancyConfig.Enabled)
+ })
+
+ t.Run("List tenants of a class", func(t *testing.T) {
+ // START ListTenants
+ tenants, err := client.Schema().TenantsGetter().
+ WithClassName("MultiTenancyClass").
+ Do(ctx)
+ // END ListTenants
+ require.NoError(t, err)
+ require.Len(t, tenants, 2)
+ })
+
+ t.Run("Remove tenants from a class", func(t *testing.T) {
+ // START RemoveTenants
+ client.Schema().TenantsDeleter().
+ WithClassName("MultiTenancyClass").
+ WithTenants("tenantB", "tenantX"). // tenantX will be ignored
+ Do(ctx)
+ // END RemoveTenants
+
+ tenants, err := client.Schema().TenantsGetter().WithClassName(className).Do(ctx)
+ require.NoError(t, err)
+ require.Len(t, tenants, 1)
+ })
+
+ t.Run("Create MT object", func(t *testing.T) {
+ // START CreateMtObject
+ object, err := client.Data().Creator().
+ WithClassName("MultiTenancyClass"). // The class to which the object will be added
+ WithProperties(map[string]interface{}{
+ "question": "This vector DB is OSS & supports automatic property type inference on import",
+ }).
+ // highlight-start
+ WithTenant("tenantA"). // The tenant to which the object will be added
+ // highlight-end
+ Do(ctx)
+ // END CreateMtObject
+
+ require.NoError(t, err)
+ require.NotNil(t, object)
+ assert.Equal(t, "tenantA", object.Object.Tenant)
+ })
+
+ t.Run("Search MT", func(t *testing.T) {
+ // START Search
+ result, err := client.GraphQL().Get().
+ WithClassName("MultiTenancyClass").
+ WithFields(graphql.Field{Name: "question"}).
+ // highlight-start
+ WithTenant("tenantA").
+ // highlight-end
+ Do(ctx)
+ // END Search
+
+ require.NoError(t, err)
+ require.NotNil(t, result)
+ require.Empty(t, result.Errors)
+ agg := result.Data["Get"].(map[string]interface{})
+ objects := agg[className].([]interface{})
+ require.Len(t, objects, 1)
+ obj := objects[0]
+ question := obj.(map[string]interface{})["question"]
+ assert.NotNil(t, question)
+ })
+
+ t.Run("Add cross-reference", func(t *testing.T) {
+ objects, err := client.Data().ObjectsGetter().WithClassName(className).WithTenant("tenantA").Do(ctx)
+ require.NoError(t, err)
+ require.Len(t, objects, 1)
+
+ object := objects[0]
+
+ categoryWrapper, err := client.Data().Creator().
+ WithClassName("JeopardyCategory").
+ WithProperties(map[string]interface{}{
+ "category": "Software",
+ }).
+ Do(ctx)
+ require.NoError(t, err)
+ require.NotNil(t, categoryWrapper)
+
+ category := categoryWrapper.Object
+
+ // START AddCrossRef
+ // Add the cross-reference property to the multi-tenancy class
+ client.Schema().PropertyCreator().
+ WithClassName("MultiTenancyClass").
+ WithProperty(&models.Property{
+ Name: "hasCategory",
+ DataType: []string{"JeopardyCategory"},
+ }).
+ Do(ctx)
+
+ // Create the cross-reference from MultiTenancyClass object to the JeopardyCategory object
+ client.Data().ReferenceCreator().
+ WithClassName("MultiTenancyClass").
+ // highlight-start
+ WithTenant("tenantA").
+ // highlight-end
+ WithID(object.ID.String()). // MultiTenancyClass object id (a Jeopardy question)
+ WithReferenceProperty("hasCategory").
+ WithReference(client.Data().ReferencePayloadBuilder().
+ WithClassName("JeopardyCategory").
+ WithID(category.ID.String()).
+ Payload()).
+ Do(ctx)
+ // END AddCrossRef
+
+ objs, err := client.Data().ObjectsGetter().
+ WithClassName(className).
+ WithID(object.ID.String()).
+ WithTenant("tenantA").
+ Do(ctx)
+ require.NoError(t, err)
+ require.Len(t, objs, 1)
+ hasCategory := objs[0].Properties.(map[string]interface{})["hasCategory"]
+ require.NotNil(t, hasCategory)
+ href := hasCategory.([]interface{})[0].(map[string]interface{})["href"]
+ assert.True(t, strings.Contains(href.(string), fmt.Sprintf("/objects/JeopardyCategory/%v", category.ID)))
+ })
+}
diff --git a/_includes/code/howto/go/docs/manage-data.read-all-objects_test.go b/_includes/code/howto/go/docs/manage-data.read-all-objects_test.go
new file mode 100644
index 0000000000..32ad697779
--- /dev/null
+++ b/_includes/code/howto/go/docs/manage-data.read-all-objects_test.go
@@ -0,0 +1,165 @@
+// How-to: Manage data -> Read all objects
+// TODO: write tests, this is only an implementation, needs tests
+package docs
+
+import (
+ "context"
+ "fmt"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/require"
+ // CursorExample // Retrieve data
+ "github.com/weaviate/weaviate-go-client/v4/weaviate"
+ "github.com/weaviate/weaviate-go-client/v4/weaviate/auth"
+ "github.com/weaviate/weaviate-go-client/v4/weaviate/graphql"
+ "github.com/weaviate/weaviate/entities/models"
+ // END CursorExample // Use this function to retrieve data
+)
+
+func Test_ManageDataReadAllObjects(t *testing.T) {
+ ctx := context.Background()
+ t.Run("Read all objects", func(t *testing.T) {
+ // CursorExample // Retrieve data
+
+ sourceClient, err := weaviate.NewClient(weaviate.Config{
+ Scheme: "https",
+ Host: "some-endpoint.weaviate.network", // Replace with your Weaviate URL
+ AuthConfig: auth.ApiKey{
+ Value: "YOUR-WEAVIATE-API-KEY", // If auth enabled. Replace w/ your Weaviate instance API key.
+ },
+ })
+ if err != nil {
+ // handle error
+ panic(err)
+ }
+
+ batchSize := 20
+ className := "WineReview"
+ classProperties := []string{"title"}
+
+ getBatchWithCursor := func(client weaviate.Client,
+ className string, classProperties []string, batchSize int, cursor string) (*models.GraphQLResponse, error) {
+ fields := []graphql.Field{}
+ for _, prop := range classProperties {
+ fields = append(fields, graphql.Field{Name: prop})
+ }
+ fields = append(fields, graphql.Field{Name: "_additional { id vector }"})
+
+ get := client.GraphQL().Get().
+ WithClassName(className).
+ // highlight-start
+ // Optionally retrieve the vector embedding by adding `vector` to the _additional fields
+ WithFields(fields...).
+ // highlight-end
+ WithLimit(batchSize)
+
+ if cursor != "" {
+ return get.WithAfter(cursor).Do(context.Background())
+ }
+ return get.Do(context.Background())
+ }
+ // Use this function to retrieve data
+
+ // START FetchClassDefinition
+ classDef, err := sourceClient.Schema().ClassGetter().WithClassName(className).Do(ctx)
+ // END FetchClassDefinition
+ require.NoError(t, err)
+
+ // Restore to a new (target) instance
+
+ targetClient, err := weaviate.NewClient(weaviate.Config{
+ Scheme: "https",
+ Host: "some-endpoint.weaviate.network", // Replace with your Weaviate URL
+ })
+ if err != nil {
+ // handle error
+ panic(err)
+ }
+
+ targetClient.Schema().ClassCreator().WithClass(classDef).Do(ctx)
+ // Finished restoring to the target instance // END CursorExample
+
+ // TODO: tests
+
+ // Restore to a new (target) instance // CursorExample
+ targetBatcher := targetClient.Batch().ObjectsBatcher()
+ cursor := ""
+
+ getObjectProperties := func(results *models.GraphQLResponse,
+ className string) ([]map[string]interface{}, error) {
+ if len(results.Errors) > 0 {
+ // handle errors
+ errorMessages := make([]string, len(results.Errors))
+ for i, gqlErr := range results.Errors {
+ errorMessages[i] = fmt.Sprintf("path: %v message: %v", gqlErr.Path, gqlErr.Message)
+ }
+ return nil, fmt.Errorf("error: %v", strings.Join(errorMessages, ", "))
+ }
+ get := results.Data["Get"].(map[string]interface{})
+ objects := get[className].([]interface{})
+ res := make([]map[string]interface{}, len(objects))
+ for i, obj := range objects {
+ res[i] = obj.(map[string]interface{})
+ }
+ return res, nil
+ }
+
+ mustGetVector := func(v interface{}) models.C11yVector {
+ vec, ok := v.([]interface{})
+ if ok {
+ vector := make(models.C11yVector, len(vec))
+ for i := range vec {
+ vector[i] = vec[i].(float32)
+ }
+ return vector
+ }
+ panic("argument is not an array")
+ }
+
+ // Batch import all objects to the target instance
+ for {
+ // From the SOURCE instance, get the next group of objects
+ results, err := getBatchWithCursor(*sourceClient, className, classProperties, batchSize, cursor)
+ if err != nil {
+ // handle errors
+ panic(err)
+ }
+ objectProperties, err := getObjectProperties(results, className)
+ if err != nil {
+ // handle errors
+ panic(err)
+ }
+ // If empty, we're finished
+ if len(objectProperties) == 0 {
+ break
+ }
+ // Otherwise, add the objects to the batch to be added to the target instance
+ for _, objProp := range objectProperties {
+ _additional := objProp["_additional"]
+ properties := map[string]interface{}{}
+ for name, value := range objProp {
+ if name != "_additional" {
+ properties[name] = value
+ }
+ }
+
+ targetBatcher.WithObjects(&models.Object{
+ Class: className,
+ Properties: properties,
+ // highlight-start
+ // Can update the vector if it was included in _additional above
+ Vector: mustGetVector(_additional.(map[string]interface{})["vector"]),
+ // highlight-end
+ })
+ }
+ resp, err := targetBatcher.Do(ctx)
+ if err != nil {
+ // handle errors
+ panic(err)
+ }
+ fmt.Printf("Imported %v objects...", len(resp))
+ }
+ // Finished restoring to the target instance // END CursorExample
+ })
+}
diff --git a/_includes/code/howto/go/docs/manage-data.read_test.go b/_includes/code/howto/go/docs/manage-data.read_test.go
new file mode 100644
index 0000000000..7f771a5d94
--- /dev/null
+++ b/_includes/code/howto/go/docs/manage-data.read_test.go
@@ -0,0 +1,65 @@
+// How-to: Manage-data -> (Batch) Import items
+package docs
+
+import (
+ "context"
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "github.com/weaviate/weaviate-go-client/v4/weaviate"
+ "github.com/weaviate/weaviate-go-client/v4/weaviate/auth"
+)
+
+func Test_ManageDataRead(t *testing.T) {
+ ctx := context.Background()
+ scheme := "https"
+ host := "edu-demo.weaviate.network"
+ apiKey := "learn-weaviate"
+
+ config := weaviate.Config{Scheme: scheme, Host: host, AuthConfig: auth.ApiKey{Value: apiKey}}
+ client, err := weaviate.NewClient(config)
+ require.NoError(t, err)
+
+ t.Run("Read object", func(t *testing.T) {
+ // ReadObject START
+ objects, err := client.Data().ObjectsGetter().
+ WithClassName("JeopardyQuestion").
+ WithID("00ff6900-e64f-5d94-90db-c8cfa3fc851b").
+ Do(ctx)
+ if err != nil {
+ // handle error
+ panic(err)
+ }
+
+ for i, obj := range objects {
+ fmt.Printf("object[%v]: %+v\n", i, *obj)
+ }
+ // ReadObject END
+ require.Len(t, objects, 1)
+ assert.Equal(t, "San Francisco", objects[0].Properties.(map[string]interface{})["answer"])
+ })
+
+ t.Run("Read object with vector", func(t *testing.T) {
+ // ReadObjectWithVector START
+ objects, err := client.Data().ObjectsGetter().
+ WithClassName("JeopardyQuestion").
+ WithID("00ff6900-e64f-5d94-90db-c8cfa3fc851b").
+ // highlight-start
+ WithVector().
+ // highlight-end
+ Do(ctx)
+ if err != nil {
+ // handle error
+ panic(err)
+ }
+
+ for i, obj := range objects {
+ fmt.Printf("object[%v]: %+v\n", i, *obj)
+ }
+ // ReadObjectWithVector END
+ require.Len(t, objects, 1)
+ assert.Equal(t, 1536, len(objects[0].Vector))
+ })
+}
diff --git a/_includes/code/howto/go/docs/manage-data.update_test.go b/_includes/code/howto/go/docs/manage-data.update_test.go
new file mode 100644
index 0000000000..7ce49138d7
--- /dev/null
+++ b/_includes/code/howto/go/docs/manage-data.update_test.go
@@ -0,0 +1,148 @@
+// How-to: Manage-data -> Create objects
+package docs
+
+import (
+ "context"
+ "fmt"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "github.com/weaviate/weaviate-go-client/v4/weaviate"
+ "github.com/weaviate/weaviate/entities/models"
+ "weaviate.io/docs/docs/helper"
+)
+
+func Test_ManageDataUpdate(t *testing.T) {
+ ctx := context.Background()
+ scheme := helper.EnvScheme("http")
+ host := helper.EnvHost("localhost")
+ port := helper.EnvPort("8080")
+ openaiApiKey := helper.Env("OPENAI_APIKEY", "_dummy_")
+
+ config := weaviate.Config{Scheme: scheme, Host: host + ":" + port, Headers: map[string]string{
+ "X-Openai-Api-Key": openaiApiKey,
+ }}
+ client, err := weaviate.NewClient(config)
+ require.NoError(t, err)
+
+ err = client.Schema().AllDeleter().Do(ctx)
+ require.NoError(t, err)
+
+ className := "JeopardyQuestion"
+
+ t.Run("define the class", func(t *testing.T) {
+ jeopardyClass := &models.Class{
+ Class: className,
+ Description: "A Jeopardy! question",
+ Vectorizer: "text2vec-openai",
+ }
+
+ err := client.Schema().ClassCreator().
+ WithClass(jeopardyClass).
+ Do(ctx)
+
+ require.NoError(t, err)
+ })
+
+ t.Run("update properties", func(t *testing.T) {
+ // DelProps START
+ delProps := func(uuid, className string, propNames ...string) (bool, error) {
+ objs, err := client.Data().ObjectsGetter().WithID(uuid).WithClassName(className).Do(ctx)
+ if err != nil {
+ return false, err
+ }
+ if objs == nil || len(objs) == 0 {
+ return false, fmt.Errorf("object with id: %v not found", uuid)
+ }
+ if objs[0].Properties == nil {
+ return false, fmt.Errorf("object with id: %v has no properties", uuid)
+ }
+ properties := objs[0].Properties.(map[string]interface{})
+ for _, propName := range propNames {
+ delete(properties, propName)
+ }
+ err = client.Data().Updater().
+ WithID(uuid).
+ WithClassName(className).
+ WithProperties(properties).
+ Do(ctx)
+ return err == nil, err
+ }
+
+ // DelProps END
+
+ objWrapper, err := client.Data().Creator().
+ WithClassName(className).
+ WithProperties(map[string]interface{}{
+ "question": "Test question",
+ "answer": "Test answer",
+ "points": -1,
+ }).
+ Do(ctx)
+ require.NoError(t, err)
+ require.NotNil(t, objWrapper)
+
+ // UpdateProps START // Replace START // DelProps START
+ id := "..." // replace with the id of the object you want to update
+ // UpdateProps END // Replace END // DelProps END
+ _ = id
+ id = objWrapper.Object.ID.String()
+
+ // UpdateProps START
+ client.Data().Updater().
+ // highlight-start
+ WithMerge(). // merges properties into the object
+ // highlight-end
+ WithID(id).
+ WithClassName("JeopardyQuestion").
+ WithProperties(map[string]interface{}{
+ "points": 100,
+ }).
+ Do(ctx)
+ // UpdateProps END
+
+ objs, err := client.Data().ObjectsGetter().WithID(id).WithClassName(className).Do(ctx)
+ require.NoError(t, err)
+ require.NotNil(t, objs)
+ require.Len(t, objs, 1)
+ assert.Equal(t, float64(100), objs[0].Properties.(map[string]interface{})["points"])
+ assert.Equal(t, "Test question", objs[0].Properties.(map[string]interface{})["question"])
+ assert.Equal(t, "Test answer", objs[0].Properties.(map[string]interface{})["answer"])
+
+ // Replace START
+ // highlight-start
+ client.Data().Updater(). // replaces the entire object
+ // highlight-end
+ WithID(id).
+ WithClassName("JeopardyQuestion").
+ WithProperties(map[string]interface{}{
+ "answer": "Replaced",
+ // The other properties will be deleted
+ }).
+ Do(ctx)
+ // Replace END
+
+ objs, err = client.Data().ObjectsGetter().WithID(id).WithClassName(className).Do(ctx)
+ require.NoError(t, err)
+ require.NotNil(t, objs)
+ require.Len(t, objs, 1)
+ assert.Nil(t, objs[0].Properties.(map[string]interface{})["points"])
+ assert.Nil(t, objs[0].Properties.(map[string]interface{})["question"])
+ assert.Equal(t, "Replaced", objs[0].Properties.(map[string]interface{})["answer"])
+
+ // DelProps START
+ isUpdated, err := delProps(id, "JeopardyQuestion", "answer")
+ // DelProps END
+ require.NoError(t, err)
+ require.True(t, isUpdated)
+
+ objs, err = client.Data().ObjectsGetter().WithID(id).WithClassName(className).Do(ctx)
+ require.NoError(t, err)
+ require.NotNil(t, objs)
+ require.Len(t, objs, 1)
+ assert.Nil(t, objs[0].Properties.(map[string]interface{})["points"])
+ assert.Nil(t, objs[0].Properties.(map[string]interface{})["question"])
+ assert.Nil(t, objs[0].Properties.(map[string]interface{})["answer"])
+ })
+}
diff --git a/_includes/code/howto/go/go.mod b/_includes/code/howto/go/go.mod
new file mode 100644
index 0000000000..7c20fdc186
--- /dev/null
+++ b/_includes/code/howto/go/go.mod
@@ -0,0 +1,40 @@
+module weaviate.io/docs
+
+go 1.20
+
+require (
+ github.com/go-openapi/strfmt v0.21.7
+ github.com/google/uuid v1.3.1
+ github.com/stretchr/testify v1.8.4
+ github.com/weaviate/weaviate v1.21.0
+ github.com/weaviate/weaviate-go-client/v4 v4.10.0
+)
+
+require (
+ github.com/PuerkitoBio/purell v1.1.1 // indirect
+ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
+ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/go-openapi/analysis v0.21.2 // indirect
+ github.com/go-openapi/errors v0.20.3 // indirect
+ github.com/go-openapi/jsonpointer v0.19.5 // indirect
+ github.com/go-openapi/jsonreference v0.19.6 // indirect
+ github.com/go-openapi/loads v0.21.1 // indirect
+ github.com/go-openapi/spec v0.20.4 // indirect
+ github.com/go-openapi/swag v0.22.3 // indirect
+ github.com/go-openapi/validate v0.21.0 // indirect
+ github.com/golang/protobuf v1.5.3 // indirect
+ github.com/josharian/intern v1.0.0 // indirect
+ github.com/mailru/easyjson v0.7.7 // indirect
+ github.com/mitchellh/mapstructure v1.5.0 // indirect
+ github.com/oklog/ulid v1.3.1 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ go.mongodb.org/mongo-driver v1.11.3 // indirect
+ golang.org/x/net v0.10.0 // indirect
+ golang.org/x/oauth2 v0.8.0 // indirect
+ golang.org/x/text v0.9.0 // indirect
+ google.golang.org/appengine v1.6.7 // indirect
+ google.golang.org/protobuf v1.30.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/_includes/code/howto/go/go.sum b/_includes/code/howto/go/go.sum
new file mode 100644
index 0000000000..52d09e4e53
--- /dev/null
+++ b/_includes/code/howto/go/go.sum
@@ -0,0 +1,208 @@
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
+github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
+github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
+github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
+github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
+github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/go-openapi/analysis v0.21.2 h1:hXFrOYFHUAMQdu6zwAiKKJHJQ8kqZs1ux/ru1P1wLJU=
+github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY=
+github.com/go-openapi/errors v0.19.8/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
+github.com/go-openapi/errors v0.19.9/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M=
+github.com/go-openapi/errors v0.20.3 h1:rz6kiC84sqNQoqrtulzaL/VERgkoCyB6WdEkc2ujzUc=
+github.com/go-openapi/errors v0.20.3/go.mod h1:Z3FlZ4I8jEGxjUK+bugx3on2mIAk4txuAOhlsB1FSgk=
+github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
+github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
+github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
+github.com/go-openapi/loads v0.21.1 h1:Wb3nVZpdEzDTcly8S4HMkey6fjARRzb7iEaySimlDW0=
+github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g=
+github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
+github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
+github.com/go-openapi/strfmt v0.21.0/go.mod h1:ZRQ409bWMj+SOgXofQAGTIo2Ebu72Gs+WaRADcS5iNg=
+github.com/go-openapi/strfmt v0.21.1/go.mod h1:I/XVKeLc5+MM5oPNN7P6urMOpuLXEcNrCX/rPGuWb0k=
+github.com/go-openapi/strfmt v0.21.7 h1:rspiXgNWgeUzhjo1YU01do6qsahtJNByjLVbPLNHb8k=
+github.com/go-openapi/strfmt v0.21.7/go.mod h1:adeGTkxE44sPyLk0JV235VQAO/ZXUr8KAzYjclFs3ew=
+github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
+github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
+github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
+github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
+github.com/go-openapi/validate v0.21.0 h1:+Wqk39yKOhfpLqNLEC0/eViCkzM5FVXVqrvt526+wcI=
+github.com/go-openapi/validate v0.21.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
+github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY=
+github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg=
+github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
+github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
+github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs=
+github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
+github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI=
+github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk=
+github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28=
+github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo=
+github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk=
+github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw=
+github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360=
+github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg=
+github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE=
+github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8=
+github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
+github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc=
+github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
+github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4=
+github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ=
+github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0=
+github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
+github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
+github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
+github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
+github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
+github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
+github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
+github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
+github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
+github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
+github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
+github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
+github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
+github.com/weaviate/weaviate v1.21.0 h1:hP0g74nr9OQEMfuvS5niA+0OEBLiQ/faGuqkMweIuDo=
+github.com/weaviate/weaviate v1.21.0/go.mod h1:SlIZ2aw5wiDAPe4iRLkSFTTBFbrCd33DfyvicBpOfYk=
+github.com/weaviate/weaviate-go-client/v4 v4.10.0 h1:Kpd3w6P9jc4Z5ejFgcillrwRNC0hUudnIZa48P6p/XA=
+github.com/weaviate/weaviate-go-client/v4 v4.10.0/go.mod h1:1wUSKRvtHFDq5s1u7tyr7cYSwPODDt3zVbNpS8VhJ0s=
+github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
+github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
+github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
+github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
+github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
+github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
+go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg=
+go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng=
+go.mongodb.org/mongo-driver v1.11.3 h1:Ql6K6qYHEzB6xvu4+AU0BoRoqf9vFPcc4o7MUIdPW8Y=
+go.mongodb.org/mongo-driver v1.11.3/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
+golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
+golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
+golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
+google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
+google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/_includes/code/howto/java/pom.xml b/_includes/code/howto/java/pom.xml
new file mode 100644
index 0000000000..01270ce8ce
--- /dev/null
+++ b/_includes/code/howto/java/pom.xml
@@ -0,0 +1,63 @@
+
+
+ 4.0.0
+
+ io.weaviate
+ docs
+ 1.0-SNAPSHOT
+
+
+
+ Andrzej Liszka
+ andrzej@weaviate.io
+ Weaviate B.V.
+ https://www.weaviate.io
+
+
+
+
+ UTF-8
+ UTF-8
+ UTF-8
+ 1.8
+ 1.8
+
+ 4.3.0
+ 5.9.3
+ 3.24.2
+ 3.1.2
+
+
+
+
+ io.weaviate
+ client
+ ${weaviate.client.version}
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ ${junit.version}
+ test
+
+
+ org.assertj
+ assertj-core
+ ${assertj-core.version}
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${surefire-plugin.version}
+
+
+
+
diff --git a/_includes/code/howto/java/src/test/java/io/weaviate/docs/helper/AssertHelper.java b/_includes/code/howto/java/src/test/java/io/weaviate/docs/helper/AssertHelper.java
new file mode 100644
index 0000000000..ff1848230f
--- /dev/null
+++ b/_includes/code/howto/java/src/test/java/io/weaviate/docs/helper/AssertHelper.java
@@ -0,0 +1,84 @@
+package io.weaviate.docs.helper;
+
+import io.weaviate.client.base.Result;
+import io.weaviate.client.v1.data.model.WeaviateObject;
+import io.weaviate.client.v1.graphql.model.GraphQLResponse;
+import io.weaviate.client.v1.graphql.query.fields.Field;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import static org.assertj.core.api.Assertions.as;
+import static org.assertj.core.api.Assertions.assertThat;
+import io.weaviate.client.WeaviateClient;
+
+public class AssertHelper {
+ public static void deleteClass(WeaviateClient client, String className) {
+ Result result = client.schema().classDeleter().withClassName(className).run();
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .returns(true, Result::getResult);
+ }
+
+ public static void checkNumberOfResults(WeaviateClient client, String className, Double count) {
+ Result result = client.graphQL()
+ .aggregate()
+ .withClassName(className)
+ .withFields(Field.builder().name("meta { count }").build())
+ .run();
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .extracting(Result::getResult).isNotNull()
+ .extracting(resp -> ((Map, ?>) resp.getData()).get("Aggregate")).isNotNull()
+ .extracting(aggregate -> ((Map, ?>) aggregate).get(className)).isNotNull()
+ .extracting(clazz -> ((List>) clazz).get(0)).isNotNull()
+ .extracting(meta -> ((Map, ?>) meta).get("meta")).isNotNull()
+ .returns(count, metaCount -> ((Map, ?>) metaCount).get("count"));
+ }
+
+ public static boolean delProps(WeaviateClient client, String uuid, String className, String ...propNames) {
+ Result> result = client.data().objectsGetter().withID(uuid).withClassName(className).run();
+ if (!result.hasErrors() && result.getResult() != null) {
+ WeaviateObject objectData = result.getResult().get(0);
+ for (String propName: propNames) {
+ objectData.getProperties().remove(propName);
+ }
+ // Replace the object
+ Result update = client.data().updater()
+ .withID(uuid)
+ .withClassName(className)
+ .withProperties(objectData.getProperties())
+ .run();
+ return update.getResult() != null && update.getResult().equals(true);
+ }
+ return false;
+ }
+
+ public static void assertCrossRefHref(Result> result, String propName, String ...href) {
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .extracting(Result::getResult).isNotNull()
+ .extracting(l -> l.get(0)).isNotNull()
+ .extracting(WeaviateObject::getProperties).isNotNull()
+ .extracting(props -> props.get(propName)).isNotNull()
+ .satisfies(p -> {
+ assertThat(p)
+ .isInstanceOf(List.class)
+ .satisfies(prop -> {
+ for (Object propVal: (List>) prop) {
+ assertThat(propVal).isNotNull()
+ .isInstanceOf(Map.class)
+ .extracting(prop2 -> ((Map, ?>) prop2).get("href")).isNotNull()
+ .satisfies(hrefValue -> {
+ assertThat(Arrays.stream(href).filter(v -> v.equals(hrefValue))).isNotNull();
+ });
+ }
+ });
+ });
+ }
+}
diff --git a/_includes/code/howto/java/src/test/java/io/weaviate/docs/helper/EnvHelper.java b/_includes/code/howto/java/src/test/java/io/weaviate/docs/helper/EnvHelper.java
new file mode 100644
index 0000000000..abdf5b7ce5
--- /dev/null
+++ b/_includes/code/howto/java/src/test/java/io/weaviate/docs/helper/EnvHelper.java
@@ -0,0 +1,29 @@
+package io.weaviate.docs.helper;
+
+import java.util.Optional;
+
+public class EnvHelper {
+
+ private static final String ENV_SCHEME = "WEAVIATE_SCHEME";
+ private static final String ENV_HOST = "WEAVIATE_HOST";
+ private static final String ENV_PORT = "WEAVIATE_PORT";
+
+ private EnvHelper() {
+ }
+
+ public static String scheme(String defaultScheme) {
+ return env(ENV_SCHEME, defaultScheme);
+ }
+
+ public static String host(String defaultHost) {
+ return env(ENV_HOST, defaultHost);
+ }
+
+ public static String port(String defaultPort) {
+ return env(ENV_PORT, defaultPort);
+ }
+
+ public static String env(String envName, String def) {
+ return Optional.ofNullable(System.getenv(envName)).orElse(def);
+ }
+}
diff --git a/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.classes.java b/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.classes.java
new file mode 100644
index 0000000000..da52213736
--- /dev/null
+++ b/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.classes.java
@@ -0,0 +1,164 @@
+// How-to: Manage-Data -> Classes
+package io.weaviate.docs;
+
+import com.google.gson.GsonBuilder;
+import io.weaviate.client.Config;
+import io.weaviate.client.WeaviateClient;
+import io.weaviate.client.base.Result;
+import io.weaviate.client.v1.misc.model.DistanceType;
+import io.weaviate.client.v1.misc.model.VectorIndexConfig;
+import io.weaviate.client.v1.schema.model.Schema;
+import io.weaviate.client.v1.schema.model.WeaviateClass;
+import io.weaviate.docs.helper.EnvHelper;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Tag("crud")
+@Tag("classes")
+class ManageDataClassesTest {
+
+ private static WeaviateClient client;
+
+ @BeforeAll
+ public static void beforeAll() {
+ String scheme = EnvHelper.scheme("http");
+ String host = EnvHelper.host("localhost");
+ String port = EnvHelper.port("8080");
+
+ Config config = new Config(scheme, host + ":" + port);
+ client = new WeaviateClient(config);
+
+ Result result = client.schema().allDeleter().run();
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .returns(true, Result::getResult);
+ }
+
+ @Test
+ public void shouldManageDataClasses() {
+ // START CreateClass // START ReadOneClass // START UpdateClass
+ String className = "Article";
+
+ // END CreateClass // END ReadOneClass // END UpdateClass
+
+ createClass(className);
+ readOneClass(className);
+ readAllClasses();
+ updateClass(className);
+ }
+
+ private void createClass(String className) {
+ // START CreateClass
+ WeaviateClass emptyClass = WeaviateClass.builder()
+ .className(className)
+ .build();
+
+ // Add the class to the schema
+ Result result = client.schema().classCreator()
+ .withClass(emptyClass)
+ .run();
+
+ // END CreateClass
+
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .returns(true, Result::getResult);
+ }
+
+ private void readOneClass(String className) {
+ // START ReadOneClass
+ Result result = client.schema().classGetter()
+ .withClassName(className)
+ .run();
+
+ // END ReadOneClass
+
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .extracting(Result::getResult).isNotNull()
+ .extracting(WeaviateClass::getClassName).isEqualTo(className);
+
+ print(result);
+ }
+
+ private void readAllClasses() {
+ // START ReadAllClasses
+ Result result = client.schema().getter()
+ .run();
+
+ // END ReadAllClasses
+
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .extracting(Result::getResult).isNotNull()
+ .extracting(Schema::getClasses).asList()
+ .hasSize(1);
+
+ print(result);
+ }
+
+ private void updateClass(String className) {
+ Result delResult = client.schema().classDeleter()
+ .withClassName(className)
+ .run();
+
+ assertThat(delResult).isNotNull()
+ .withFailMessage(() -> delResult.getError().toString())
+ .returns(false, Result::hasErrors)
+ .returns(true, Result::getResult);
+
+ // START UpdateClassTODO
+ // Define class
+ WeaviateClass originalClass = WeaviateClass.builder()
+ .className(className)
+ .vectorIndexConfig(VectorIndexConfig.builder()
+ .distance(DistanceType.COSINE) // Note the distance metric
+ .build())
+ .build();
+
+ // Add the class to the schema
+ Result result = client.schema().classCreator()
+ .withClass(originalClass)
+ .run();
+
+ // END UpdateClassTODO
+
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .returns(true, Result::getResult);
+
+ // START UpdateClassTODO
+ // Define updated class
+ WeaviateClass updatedClass = WeaviateClass.builder()
+ .className(className)
+ .vectorIndexConfig(VectorIndexConfig.builder()
+ .distance(DistanceType.DOT) // Note the distance metric
+ .build())
+ .build();
+
+ // Update the class definition
+ // TODO Not yet available in JAVA
+
+ // END UpdateClassTODO
+ }
+
+ private void print(Result result) {
+ // START ReadOneClass // START ReadAllClasses
+ String json = new GsonBuilder().setPrettyPrinting().create().toJson(result.getResult());
+ System.out.println(json);
+ // END ReadOneClass // END ReadAllClasses
+ }
+}
diff --git a/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.create.java b/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.create.java
new file mode 100644
index 0000000000..6054b1a7c6
--- /dev/null
+++ b/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.create.java
@@ -0,0 +1,218 @@
+// How-to: Manage-data -> Create objects
+package io.weaviate.docs;
+
+import com.google.gson.GsonBuilder;
+import io.weaviate.client.Config;
+// START JSON streaming // START CSV streaming
+import io.weaviate.client.WeaviateClient;
+// END JSON streaming // END CSV streaming
+import io.weaviate.client.base.Result;
+import io.weaviate.client.base.WeaviateError;
+import io.weaviate.client.v1.data.model.WeaviateObject;
+import io.weaviate.client.v1.schema.model.DataType;
+import io.weaviate.client.v1.schema.model.Property;
+import io.weaviate.client.v1.schema.model.WeaviateClass;
+import io.weaviate.docs.helper.EnvHelper;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Tag("crud")
+@Tag("create")
+class ManageDataCreateTest {
+
+ private static final int MAX_ROWS_TO_IMPORT = 50; // limit vectorization calls
+ private static WeaviateClient client;
+
+ @BeforeAll
+ public static void beforeAll() {
+ String scheme = EnvHelper.scheme("http");
+ String host = EnvHelper.host("localhost");
+ String port = EnvHelper.port("8080");
+ String openaiApiKey = EnvHelper.env("OPENAI_APIKEY", "_dummy_");
+
+ Config config = new Config(scheme, host + ":" + port, new HashMap() {{
+ put("X-Openai-Api-Key", openaiApiKey);
+ }});
+ client = new WeaviateClient(config);
+
+ Result result = client.schema().allDeleter().run();
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .returns(true, Result::getResult);
+ }
+
+ @Test
+ public void shouldManageDataCreate() {
+ String className = "JeopardyQuestion";
+
+ createClass(className);
+ createObject(className);
+ createObjectWithIdAndVector(className);
+ createObjectWithDeterministicId(className);
+ validateObject(className);
+ }
+
+ private void createClass(String className) {
+ WeaviateClass jeopardyClass = WeaviateClass.builder()
+ .className(className)
+ .description("A Jeopardy! question")
+ .vectorizer("text2vec-openai")
+ .properties(Arrays.asList(
+ Property.builder()
+ .name("question")
+ .dataType(Arrays.asList(DataType.TEXT))
+ .build(),
+ Property.builder()
+ .name("answer")
+ .dataType(Arrays.asList(DataType.TEXT))
+ .build()
+ ))
+ .build();
+
+ Result result = client.schema().classCreator()
+ .withClass(jeopardyClass)
+ .run();
+
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .returns(true, Result::getResult);
+ }
+
+ private void createObject(String className) {
+ // CreateObject START
+ Result result = client.data().creator()
+ .withClassName("JeopardyQuestion")
+ .withProperties(new HashMap() {{
+ put("question", "This vector DB is OSS and supports automatic property type inference on import");
+ // put("answer", "Weaviate"); // schema properties can be omitted
+ put("somePropNotInTheSchema", 123); // will be automatically added as a number property
+ }})
+ .run();
+
+ // the returned value is the object
+ // CreateObject END
+
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .extracting(Result::getResult).isNotNull()
+ .returns(className, WeaviateObject::getClassName)
+ .extracting(WeaviateObject::getProperties)
+ .extracting(props -> props.get("somePropNotInTheSchema"))
+ .isEqualTo(123.);
+
+ print(result);
+ }
+
+ private void createObjectWithIdAndVector(String className) {
+ // CreateObjectWithIdAndVector START
+ Result result = client.data().creator()
+ .withClassName("JeopardyQuestion")
+ .withProperties(new HashMap() {{
+ put("question", "This vector DB is OSS and supports automatic property type inference on import");
+ put("answer", "Weaviate");
+ }})
+ // highlight-start
+ .withID("12345678-e64f-5d94-90db-c8cfa3fc1234")
+ .withVector(Collections.nCopies(1536, 0.12345f).toArray(new Float[0]))
+ // highlight-end
+ .run();
+
+ // the returned value is the object
+ // CreateObjectWithIdAndVector END
+
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .extracting(Result::getResult).isNotNull()
+ .returns(className, WeaviateObject::getClassName)
+ .returns("12345678-e64f-5d94-90db-c8cfa3fc1234", WeaviateObject::getId);
+
+ print(result);
+ }
+
+ private void createObjectWithDeterministicId(String className) {
+ // CreateObjectWithDeterministicIdTODO START
+ Map properties = new HashMap() {{
+ put("question", "This vector DB is OSS and supports automatic property type inference on import");
+ put("answer", "Weaviate");
+ }};
+
+ // highlight-start
+ // String id = "gen_uuid5(properties)"; // TODO implement
+ String id = UUID.randomUUID().toString();
+ // highlight-end
+
+ Result result = client.data().creator()
+ .withClassName(className)
+ .withProperties(properties)
+ .withID(id)
+ .run();
+
+ // the returned value is the object
+ // CreateObjectWithDeterministicIdTODO END
+
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .extracting(Result::getResult).isNotNull()
+ .returns(className, WeaviateObject::getClassName)
+ .returns(id, WeaviateObject::getId);
+
+ print(result);
+ }
+
+ private void validateObject(String className) {
+ // ValidateObject START
+ Result result = client.data()
+ // highlight-start
+ .validator()
+ // highlight-end
+ .withClassName("JeopardyQuestion")
+ .withProperties(new HashMap() {{
+ put("question", "This vector DB is OSS and supports automatic property type inference on import");
+ put("answer", "Weaviate");
+ put("thisPropShouldNotEndUpInTheSchema", -1);
+ }})
+ .withID("12345678-1234-1234-1234-123456789012")
+ .run();
+
+ // ValidateObject END
+
+ assertThat(result).isNotNull()
+ .returns(true, Result::hasErrors)
+ .extracting(Result::getError).isNotNull()
+ .extracting(WeaviateError::getMessages).isNotNull().asList()
+ .hasSizeGreaterThan(0);
+
+ // ValidateObject START
+ assertThat(result.getResult()).isFalse();
+ assertThat(result.hasErrors()).isTrue();
+ assertThat(result.getError().getMessages().get(0).getMessage())
+ .contains("invalid object: no such prop with name 'thisPropShouldNotEndUpInTheSchema' found");
+ // ValidateObject END
+ }
+
+ private void print(Result result) {
+ // CreateObject START // CreateObjectWithIdAndVector START // CreateObjectWithDeterministicIdTODO START
+ String json = new GsonBuilder().setPrettyPrinting().create().toJson(result.getResult());
+ System.out.println(json);
+ // CreateObject END // CreateObjectWithIdAndVector END // CreateObjectWithDeterministicIdTODO END
+ }
+}
diff --git a/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.cross-refs.java b/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.cross-refs.java
new file mode 100644
index 0000000000..0cee6d0156
--- /dev/null
+++ b/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.cross-refs.java
@@ -0,0 +1,201 @@
+// How-to: Manage-data -> Cross-references
+package io.weaviate.docs;
+
+import io.weaviate.client.Config;
+import io.weaviate.client.WeaviateAuthClient;
+import io.weaviate.client.WeaviateClient;
+import io.weaviate.client.base.Result;
+import io.weaviate.client.v1.auth.exception.AuthException;
+import io.weaviate.client.v1.data.model.WeaviateObject;
+import io.weaviate.client.v1.schema.model.DataType;
+import io.weaviate.client.v1.schema.model.Property;
+import io.weaviate.docs.helper.AssertHelper;
+import java.util.Collections;
+import java.util.List;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+@Tag("crud")
+@Tag("cross-refs")
+class ManageDataCrossRefsTest {
+
+ private static WeaviateClient client;
+
+ @BeforeAll
+ public static void beforeAll() throws AuthException {
+ String scheme = "https";
+ String host = "anon-endpoint.weaviate.network";
+
+ // ===== Instantiation, not shown in snippet
+ Config config = new Config(scheme, host);
+ client = new WeaviateClient(config);
+ }
+
+ @Test
+ public void shouldManageDataCrossRefs() {
+ // OneWay Java // TwoWay Java // Multiple Java // Delete Java // Update Java
+ String sfId = "00ff6900-e64f-5d94-90db-c8cfa3fc851b";
+ // END OneWay Java // END TwoWay Java // END Multiple Java // END Delete Java // END Update Java
+ // OneWay Java // TwoWay Java // Multiple Java
+ String usCitiesId = "20ffc68d-986b-5e71-a680-228dba18d7ef";
+ // END OneWay Java // END TwoWay Java // END Multiple Java // END Delete Java
+ // Multiple Java // Delete Java // Update Java
+ String museumsId = "fec50326-dfa1-53c9-90e8-63d0240bd933";
+ // END Multiple Java // END Delete Java // END Update Java
+ oneWay(sfId, usCitiesId);
+ twoWay(sfId, usCitiesId);
+ multipleCrossRefs(sfId, usCitiesId, museumsId);
+ deleteCrossRefs(sfId, usCitiesId, museumsId);
+ updateCrossRefs(sfId, museumsId);
+ }
+
+ private void oneWay(String sfId, String usCitiesId) {
+ // OneWay Java
+
+ client.data().referenceCreator()
+ .withClassName("JeopardyQuestion")
+ .withID(sfId)
+ .withReferenceProperty("hasCategory")
+ .withReference(client.data()
+ .referencePayloadBuilder()
+ .withClassName("JeopardyCategory")
+ .withID(usCitiesId)
+ .payload())
+ .run();
+ // END OneWay Java
+
+ Result> result = client.data().objectsGetter().withID(sfId).withClassName("JeopardyQuestion").run();
+ AssertHelper.assertCrossRefHref(result, "hasCategory", String.format("http://localhost:8080/v1/objects/JeopardyCategory/%s", usCitiesId));
+ }
+
+ private void twoWay(String sfId, String usCitiesId) {
+ // Delete any existing cross-references from the source and target objects
+ boolean deleted = AssertHelper.delProps(client, "JeopardyQuestion", "hasCategory");
+ assertThat(deleted).isTrue();
+ deleted = AssertHelper.delProps(client, "JeopardyCategory", "hasQuestion");
+ assertThat(deleted).isTrue();
+
+ // TwoWay Java
+
+ // First, add the "hasQuestion" cross-reference property to the JeopardyCategory class
+ client.schema().propertyCreator()
+ .withClassName("JeopardyCategory")
+ .withProperty(Property.builder()
+ .name("hasQuestion")
+ .dataType(Collections.singletonList("JeopardyQuestion"))
+ .build())
+ .run();
+
+ // For the "San Francisco" JeopardyQuestion object, add a cross-reference to the "U.S. CITIES" JeopardyCategory object
+ client.data().referenceCreator()
+ .withClassName("JeopardyQuestion")
+ .withID(usCitiesId)
+ .withReferenceProperty("hasCategory")
+ .withReference(client.data()
+ .referencePayloadBuilder()
+ .withClassName("JeopardyCategory")
+ .withID(sfId)
+ .payload())
+ .run();
+
+ // For the "U.S. CITIES" JeopardyCategory object, add a cross-reference to "San Francisco"
+ client.data().referenceCreator()
+ .withClassName("JeopardyCategory")
+ .withID(usCitiesId)
+ .withReferenceProperty("hasQuestion")
+ .withReference(client.data()
+ .referencePayloadBuilder()
+ .withClassName("JeopardyQuestion")
+ .withID(usCitiesId)
+ .payload())
+ .run();
+ // END TwoWay Java
+
+ Result> sf = client.data().objectsGetter().withID(sfId).withClassName("JeopardyQuestion").run();
+ AssertHelper.assertCrossRefHref(sf, "hasCategory", String.format("http://localhost:8080/v1/objects/JeopardyCategory/%s", usCitiesId));
+
+ Result> usCities = client.data().objectsGetter().withID(usCitiesId).withClassName("JeopardyCategory").run();
+ AssertHelper.assertCrossRefHref(usCities, "hasQuestion", String.format("http://localhost:8080/v1/objects/JeopardyQuestion/%s", sfId));
+ }
+
+ private void multipleCrossRefs(String sfId, String usCitiesId, String museumsId) {
+ // Delete any existing cross-references from the source and target objects
+ boolean deleted = AssertHelper.delProps(client, "JeopardyQuestion", "hasCategory");
+ assertThat(deleted).isTrue();
+
+ // Multiple Java
+
+ // Add to "San Francisco" the "U.S. CITIES" category
+ client.data().referenceCreator()
+ .withClassName("JeopardyQuestion")
+ .withID(sfId)
+ .withReferenceProperty("hasCategory")
+ .withReference(client.data()
+ .referencePayloadBuilder()
+ .withClassName("JeopardyCategory")
+ .withID(usCitiesId)
+ .payload())
+ .run();
+
+ // Add the "MUSEUMS" category as well
+ client.data().referenceCreator()
+ .withClassName("JeopardyQuestion")
+ .withID(sfId)
+ .withReferenceProperty("hasCategory")
+ .withReference(client.data()
+ .referencePayloadBuilder()
+ .withClassName("JeopardyCategory")
+ .withID(museumsId)
+ .payload())
+ .run();
+ // END Multiple Java
+
+ Result> sf = client.data().objectsGetter().withID(sfId).withClassName("JeopardyQuestion").run();
+ AssertHelper.assertCrossRefHref(sf, "hasCategory",
+ String.format("http://localhost:8080/v1/objects/JeopardyCategory/%s", usCitiesId),
+ String.format("http://localhost:8080/v1/objects/JeopardyCategory/%s", museumsId)
+ );
+ }
+
+ private void deleteCrossRefs(String sfId, String usCitiesId, String museumsId) {
+ // Delete Java
+
+ // From the "San Francisco" JeopardyQuestion object, delete the "MUSEUMS" category cross-reference
+ client.data().referenceDeleter()
+ .withClassName("JeopardyQuestion")
+ .withID(sfId)
+ .withReferenceProperty("hasCategory")
+ .withReference(client.data()
+ .referencePayloadBuilder()
+ .withClassName("JeopardyCategory")
+ .withID(museumsId)
+ .payload())
+ .run();
+ // END Delete Java
+
+ Result> sf = client.data().objectsGetter().withID(sfId).withClassName("JeopardyQuestion").run();
+ AssertHelper.assertCrossRefHref(sf, "hasCategory", String.format("http://localhost:8080/v1/objects/JeopardyCategory/%s", usCitiesId));
+ }
+
+ private void updateCrossRefs(String sfId, String museumsId) {
+ // Update Java
+
+ // In the "San Francisco" JeopardyQuestion object, set the "hasCategory" cross-reference only to "MUSEUMS"
+ client.data().referenceReplacer()
+ .withClassName("JeopardyQuestion")
+ .withID(sfId)
+ .withReferenceProperty("hasCategory")
+ .withReferences(client.data()
+ .referencePayloadBuilder()
+ .withClassName("JeopardyCategory")
+ .withID(museumsId)
+ .payload())
+ .run();
+ // END Update Java
+
+ Result> sf = client.data().objectsGetter().withID(sfId).withClassName("JeopardyQuestion").run();
+ AssertHelper.assertCrossRefHref(sf, "hasCategory", String.format("http://localhost:8080/v1/objects/JeopardyCategory/%s", museumsId));
+ }
+}
diff --git a/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.delete.java b/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.delete.java
new file mode 100644
index 0000000000..744b0b9e3c
--- /dev/null
+++ b/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.delete.java
@@ -0,0 +1,162 @@
+// How-to: Manage-data -> Delete objects
+package io.weaviate.docs;
+
+import io.weaviate.client.Config;
+import io.weaviate.client.WeaviateClient;
+import io.weaviate.client.base.Result;
+import io.weaviate.client.v1.batch.model.BatchDeleteOutput;
+import io.weaviate.client.v1.batch.model.BatchDeleteResponse;
+import io.weaviate.client.v1.data.model.WeaviateObject;
+import io.weaviate.client.v1.filters.Operator;
+import io.weaviate.client.v1.filters.WhereFilter;
+import io.weaviate.docs.helper.AssertHelper;
+import io.weaviate.docs.helper.EnvHelper;
+import java.util.HashMap;
+import java.util.Map;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+@Tag("crud")
+@Tag("delete")
+class ManageDataDeleteTest {
+
+ private static WeaviateClient client;
+
+ @BeforeAll
+ public static void beforeAll() {
+ String scheme = EnvHelper.scheme("http");
+ String host = EnvHelper.host("localhost");
+ String port = EnvHelper.port("8080");
+ String openaiApiKey = EnvHelper.env("OPENAI_APIKEY", "_dummy_");
+
+ Config config = new Config(scheme, host + ":" + port, new HashMap() {{
+ put("X-Openai-Api-Key", openaiApiKey);
+ }});
+ client = new WeaviateClient(config);
+
+ Result result = client.schema().allDeleter().run();
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .returns(true, Result::getResult);
+ }
+
+ @Test
+ public void shouldManageDataRead() {
+ deleteObject();
+ dryRunAndBatchDelete();
+ }
+
+ private void deleteObject() {
+ // START DeleteObject
+ String idToDelete = "..."; // replace with the id of the object you want to delete
+ // END DeleteObject
+
+ Result result = client.data().creator()
+ .withClassName("EphemeralObject")
+ .withProperties(new HashMap() {{
+ put("name", "EphemeralObjectA");
+ }})
+ .run();
+
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .extracting(Result::getResult).isNotNull()
+ .extracting(WeaviateObject::getId).isNotNull();
+
+ idToDelete = result.getResult().getId();
+
+ // START DeleteObject
+
+ client.data().deleter()
+ .withClassName("EphemeralObject") // Class of the object to be deleted
+ .withID(idToDelete)
+ .run();
+ // END DeleteObject
+
+ Result exist = client.data().checker().withClassName("EphemeralObject").withID(idToDelete).run();
+ assertThat(exist).isNotNull()
+ .withFailMessage(() -> exist.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .returns(false, Result::getResult);
+
+ AssertHelper.deleteClass(client, "EphemeralObject");
+ }
+
+ private void dryRunAndBatchDelete() {
+ final int N = 5;
+ for (int i = 0; i < N; i++) {
+ Map properties = new HashMap<>();
+ properties.put("name", String.format("EphemeralObject_%s", i));
+ Result result = client.data().creator()
+ .withClassName("EphemeralObject")
+ .withProperties(properties)
+ .run();
+
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .extracting(Result::getResult).isNotNull()
+ .extracting(WeaviateObject::getId).isNotNull();
+ }
+
+ AssertHelper.checkNumberOfResults(client, "EphemeralObject", 5.0);
+
+ Result dryRun =
+ // START DryRun
+ client.batch().objectsBatchDeleter()
+ .withClassName("EphemeralObject")
+ // Same `where` filter as in the GraphQL API
+ .withWhere(WhereFilter.builder()
+ .path("name")
+ .operator(Operator.Like)
+ .valueText("EphemeralObject*")
+ .build())
+ // highlight-start
+ .withDryRun(true)
+ .withOutput(BatchDeleteOutput.VERBOSE)
+ // highlight-end
+ .run();
+ // END DryRun
+
+ assertThat(dryRun).isNotNull()
+ .withFailMessage(() -> dryRun.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .extracting(Result::getResult).isNotNull()
+ .extracting(BatchDeleteResponse::getResults).isNotNull()
+ .returns(5L, BatchDeleteResponse.Results::getMatches);
+ AssertHelper.checkNumberOfResults(client, "EphemeralObject", 5.0);
+
+ Result batchDelete =
+ // START DeleteBatch
+ client.batch().objectsBatchDeleter()
+ .withClassName("EphemeralObject")
+ // highlight-start
+ // Same `where` filter as in the GraphQL API
+ .withWhere(WhereFilter.builder()
+ .path("name")
+ .operator(Operator.Like)
+ .valueText("EphemeralObject*")
+ .build())
+ // highlight-end
+ .run();
+ // END DeleteBatch
+
+ assertThat(batchDelete).isNotNull()
+ .withFailMessage(() -> batchDelete.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .extracting(Result::getResult).isNotNull()
+ .extracting(BatchDeleteResponse::getResults).isNotNull()
+ .returns(5L, BatchDeleteResponse.Results::getMatches);
+ AssertHelper.checkNumberOfResults(client, "EphemeralObject", 0.0);
+ }
+}
diff --git a/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.import.java b/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.import.java
new file mode 100644
index 0000000000..aa0bd599b8
--- /dev/null
+++ b/_includes/code/howto/java/src/test/java/io/weaviate/docs/manage-data.import.java
@@ -0,0 +1,217 @@
+// How-to: Manage-data -> (Batch) Import items
+package io.weaviate.docs;
+
+import io.weaviate.client.Config;
+import io.weaviate.client.WeaviateClient;
+import io.weaviate.client.base.Result;
+import io.weaviate.client.v1.batch.api.ObjectsBatcher;
+import io.weaviate.client.v1.data.model.WeaviateObject;
+import io.weaviate.client.v1.graphql.model.GraphQLResponse;
+import io.weaviate.client.v1.graphql.query.fields.Field;
+import io.weaviate.docs.helper.AssertHelper;
+import io.weaviate.docs.helper.EnvHelper;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+
+@Tag("crud")
+@Tag("import")
+class ManageDataImportTest {
+
+ private static WeaviateClient client;
+
+ @BeforeAll
+ public static void beforeAll() {
+ String scheme = EnvHelper.scheme("http");
+ String host = EnvHelper.host("localhost");
+ String port = EnvHelper.port("8080");
+ String openaiApiKey = EnvHelper.env("OPENAI_APIKEY", "_dummy_");
+
+ // ===== Instantiation, not shown in snippet
+ Config config = new Config(scheme, host + ":" + port, new HashMap() {{
+ put("X-Openai-Api-Key", openaiApiKey);
+ }});
+ client = new WeaviateClient(config);
+
+ // Clean slate
+ Result result = client.schema().allDeleter().run();
+ assertThat(result).isNotNull()
+ .withFailMessage(() -> result.getError().toString())
+ .returns(false, Result::hasErrors)
+ .withFailMessage(null)
+ .returns(true, Result::getResult);
+ }
+
+ @Test
+ public void shouldManageDataImport() {
+ basicBatchImport();
+ basicBatchImportWithCustomId();
+ basicBatchImportWithCustomVector();
+ streamingImport();
+ }
+
+ private void basicBatchImport() {
+ // BasicBatchImportExample
+ String className = "YourClassName"; // Replace with your class name
+ List