---
title: "Quick tour of Weaviate"
description: "This tutorial will show you how to use Weaviate Cloud to:"
url: https://docs.weaviate.io/weaviate/tutorials/quick-tour-of-weaviate
---

# Quick tour of Weaviate

This tutorial will show you how to use Weaviate Cloud to:

1. **Set up a Weaviate instance.**
2. **Import and vectorize your data.**
3. **Perform a semantic search and retrieval augmented generation (RAG).**

```mermaid
flowchart LR
    %% Define nodes with white backgrounds and darker borders
    A1["Install client<br> library"] --> A2["Connect to<br> Weaviate"]
    A2 --> B1["Define collection<br> (with an inference API)"]
    B1 --> B2["Import objects"]
    B2 --> C1["Semantic search<br> (nearText)"]
    C1 --> C2["RAG<br> (Generate)"]

    %% Group nodes in subgraphs with brand colors
    subgraph sg1 ["1\. Setup"]
        A1
        A2
    end

    subgraph sg2 ["2\. Populate"]
        B1
        B2
    end

    subgraph sg3 ["3\. Query"]
        C1
        C2
    end

    %% Style nodes with white background and darker borders
    style A1 fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style A2 fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style B1 fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style B2 fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style C1 fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style C2 fill:#ffffff,stroke:#B9C8DF,color:#130C49

    %% Style subgraphs with brand colors
    style sg1 fill:#ffffff,stroke:#61BD73,stroke-width:2px,color:#130C49
    style sg2 fill:#ffffff,stroke:#130C49,stroke-width:2px,color:#130C49
    style sg3 fill:#ffffff,stroke:#7AD6EB,stroke-width:2px,color:#130C49
```

---

### Prerequisites

In order to perform Retrieval Augmented Generation (RAG) in the last step, you will need an [OpenAI](https://platform.openai.com/) account and an OpenAI API key.

If you have another preferred [model provider](https://docs.weaviate.io/weaviate/model-providers), you can use that instead of OpenAI.

---

## Step 1: Set up Weaviate

### 1.1 Install a client library

We recommend using a [client library](https://docs.weaviate.io/weaviate/client-libraries) to work with Weaviate. Follow the instructions below to install one of the official client libraries, available in [Python](https://docs.weaviate.io/weaviate/client-libraries/python), [JavaScript/TypeScript](https://docs.weaviate.io/weaviate/client-libraries/typescript), [Go](https://docs.weaviate.io/weaviate/client-libraries/go), and [Java](https://docs.weaviate.io/weaviate/client-libraries/java).

**Python**

Install the latest, [Python client `v4`](https://docs.weaviate.io/weaviate/client-libraries/python), by adding `weaviate-client` to your Python environment with `pip`:

```bash
pip install -U weaviate-client
```

**JavaScript/TypeScript**

Install the latest, [JS/TS client `v3`](https://docs.weaviate.io/weaviate/client-libraries/typescript), by adding `@weaviate/node` to your project with `npm`:

```bash
npm install @weaviate/node
```

**Go (v5)**

Add `weaviate-go-client` to your project with `go get`:

```bash
go get github.com/weaviate/weaviate-go-client/v5
```

**Java**

Add this dependency to your project:

```xml
<dependency>
  <groupId>io.weaviate</groupId>
  <artifactId>client6</artifactId>
  <version>6.3.1</version> <!-- Check latest version: https://github.com/weaviate/java-client -->
</dependency>
```

**C#**

Add this package to your project:

```xml
<PackageReference Include="Weaviate.Client" Version="1.0.0" />   <!-- Check latest version: https://github.com/weaviate/java-client -->
```

### 1.2 Connect to Weaviate Cloud

**How to create a Weaviate Cloud free cluster**

Go to the [Weaviate Cloud console](https://console.weaviate.cloud) and create a free cluster.

[Embedded content](https://app.guideflow.com/embed/3r3vg6mcnp)



> [!NOTE]
>
> - Cluster provisioning typically takes 1-3 minutes.
> - When the cluster is ready, Weaviate Cloud displays a checkmark (`✔️`) next to the cluster name.
> - Note that Weaviate Cloud may add a random suffix to cluster names to ensure uniqueness.

> [!TIP]
>
> **TIP: Use the latest Weaviate version!**
>
> When possible, try to use the latest Weaviate version. New releases include cutting-edge features, performance enhancements, and critical security updates to keep your application safe and up-to-date.

Now you can connect to your Weaviate instance. You will need the:

- **REST Endpoint URL** and the
- **Administrator API Key**.

You can retrieve them both from the [WCD console](https://console.weaviate.cloud) as shown in the interactive example below.

[Embedded content](https://app.guideflow.com/embed/6kwn8ldczk)



> [!NOTE]
>
> **REST vs gRPC endpoints**
>
> Weaviate supports both REST and gRPC protocols. For Weaviate Cloud deployments, you only need to provide the REST endpoint URL - the client will automatically configure gRPC.

Once you have the **REST Endpoint URL** and the **admin API key**, you can connect to your cluster, and work with Weaviate.

The example below shows how to connect to Weaviate and perform a basic operation, like checking the cluster status.

**Python**

quickstart\_check\_readiness.py

```py
import weaviate
from weaviate.classes.init import Auth
import os

# Best practice: store your credentials in environment variables
weaviate_url = os.environ["WEAVIATE_URL"]
weaviate_api_key = os.environ["WEAVIATE_API_KEY"]

client = weaviate.connect_to_weaviate_cloud(
    cluster_url=weaviate_url,
    auth_credentials=Auth.api_key(weaviate_api_key),
)

print(client.is_ready())  # Should print: `True`

client.close()  # Free up resources
```

**JavaScript/TypeScript**

quickstart\_check\_readiness.ts

```ts
import weaviate, { WeaviateClient } from '@weaviate/node';

// Best practice: store your credentials in environment variables
const weaviateUrl = process.env.WEAVIATE_URL as string;
const weaviateApiKey = process.env.WEAVIATE_API_KEY as string;

const client: WeaviateClient = await weaviate.connectToWeaviateCloud(
  weaviateUrl, // Replace with your Weaviate Cloud URL
  {
    authCredentials: new weaviate.ApiKey(weaviateApiKey), // Replace with your Weaviate Cloud API key
  }
);

var clientReadiness = await client.isReady();
console.log(clientReadiness); // Should return `true`

client.close(); // Close the client connection
```

**Go (v5)**

quickstart/1\_check\_readiness/main.go

```go
// Set these environment variables
// WEAVIATE_HOSTNAME            your Weaviate instance hostname
// WEAVIATE_API_KEY          your Weaviate instance API key

package main

import (
    "context"
    "fmt"
    "os"

    "github.com/weaviate/weaviate-go-client/v5/weaviate"
    "github.com/weaviate/weaviate-go-client/v5/weaviate/auth"
)

func main() {
    cfg := weaviate.Config{
        Host:       os.Getenv("WEAVIATE_HOSTNAME"),
        Scheme:     "https",
        AuthConfig: auth.ApiKey{Value: os.Getenv("WEAVIATE_API_KEY")},
    }

    client, err := weaviate.NewClient(cfg)
    if err != nil {
        fmt.Println(err)
    }

    // Check the connection
    ready, err := client.Misc().ReadyChecker().Do(context.Background())
    if err != nil {
        panic(err)
    }
    fmt.Printf("%v", ready)
}
```

> [!WARNING]
>
> This client uses the `hostname` parameter (without the `https` scheme) instead of a complete `URL`.

**Java**

```java
// Best practice: store your credentials in environment variables
String weaviateUrl = System.getenv("WEAVIATE_URL");
String weaviateApiKey = System.getenv("WEAVIATE_API_KEY");

WeaviateClient client = WeaviateClient.connectToWeaviateCloud(
    weaviateUrl, // Replace with your Weaviate Cloud URL
    weaviateApiKey // Replace with your Weaviate Cloud key
);
System.out.println(client.isReady()); // Should print: `True`

client.close(); // Free up resources
```

**C#**

```csharp
// Best practice: store your credentials in environment variables
string weaviateUrl = Environment.GetEnvironmentVariable("WEAVIATE_URL");
string weaviateApiKey = Environment.GetEnvironmentVariable("WEAVIATE_API_KEY");

WeaviateClient client = await Connect.Cloud(weaviateUrl, weaviateApiKey);

// GetMeta returns server info. A successful call indicates readiness.
var meta = await client.IsReady();
Console.WriteLine(meta);
```

> [!WARNING]
>
> This client uses the `hostname` parameter (without the `https` scheme) instead of a complete `URL`.

**Curl**

```bash
# Best practice: store your credentials in environment variables
# export WEAVIATE_URL="YOUR_INSTANCE_URL"  # Your Weaviate instance URL
# export WEAVIATE_API_KEY="YOUR_API_KEY"   # Your Weaviate instance API key

curl -w "\nResponse code: %{http_code}\n" \
  -H "Authorization: Bearer $WEAVIATE_API_KEY" \
  $WEAVIATE_URL/v1/.well-known/ready

# You should see "Response code: 200" if the instance is ready
```

If you did not see any errors, you are ready to proceed. We will replace the simple cluster status check with more meaningful operations in the next steps.

---

## Step 2: Populate the database

Now, we can populate our database by first defining a collection and then adding data.

### 2.1 Define a collection

> [!NOTE]
>
> **What is a collection?**
>
> A collection is a set of objects that share the same data structure, like a table in relational databases or a collection in NoSQL databases. A collection also includes additional configurations that define how the data objects are stored and indexed.

The following example creates a *collection* called `Question` with:

- The [Weaviate Embeddings](https://docs.weaviate.io/weaviate/model-providers/weaviate/embeddings) service for creating vectors during ingestion & queries.

**Python**

> [!WARNING]
>
> **.Vectors.text2vec\_xxx with AutoSchema**
>
> Defining a collection with `Configure.Vectors.text2vec_xxx()` with Python client library `4.16.0`-`4.16.3` will throw an error if no properties are defined and `vectorize_collection_name` is not set to `True`.
>
> This is addressed in `4.16.4` of the Weaviate Python client. See this FAQ entry for more details: [Invalid properties error in Python client versions 4.16.0 to 4.16.3](https://docs.weaviate.io/weaviate/more-resources/faq#q-invalid-properties-error-when-creating-a-collection-python-client-versions-4160-to-4163).

> [!NOTE]
>
> **Python and JS/TS client - Vectorizer Configuration API Changes**
>
> Starting with Weaviate Python client `v4.16.0`, the [vectorizer configuration API has been updated](https://docs.weaviate.io/weaviate/client-libraries/python#vectorizer-api-changes-v4160).\
> Starting with Weaviate JS/TS client `v3.8.0`, the [vectorizer configuration API has been updated](https://docs.weaviate.io/weaviate/client-libraries/typescript#vectorizer-api-changes-v380).
>
> Action required: **Update to the latest client version** and migrate your code to use the [new vectorizer configuration API](https://docs.weaviate.io/weaviate/manage-collections/vector-config#specify-a-vectorizer).

quickstart\_create\_collection.py

```py
import weaviate
from weaviate.classes.init import Auth
from weaviate.classes.config import Configure
import os

# Best practice: store your credentials in environment variables
weaviate_url = os.environ["WEAVIATE_URL"]
weaviate_api_key = os.environ["WEAVIATE_API_KEY"]

client = weaviate.connect_to_weaviate_cloud(
    cluster_url=weaviate_url,  # Replace with your Weaviate Cloud URL
    auth_credentials=Auth.api_key(weaviate_api_key),  # Replace with your Weaviate Cloud key
)

questions = client.collections.create(
    name="Question",
    vector_config=Configure.Vectors.text2vec_weaviate(),  # Configure the Weaviate Embeddings integration
)

client.close()  # Free up resources
```

**JavaScript/TypeScript**

quickstart\_create\_collection.ts

```ts
import weaviate, { WeaviateClient, vectors } from '@weaviate/node';

// Best practice: store your credentials in environment variables
const weaviateUrl = process.env.WEAVIATE_URL as string;
const weaviateApiKey = process.env.WEAVIATE_API_KEY as string;

const client: WeaviateClient = await weaviate.connectToWeaviateCloud(
  weaviateUrl, // Replace with your Weaviate Cloud URL
  {
    authCredentials: new weaviate.ApiKey(weaviateApiKey), // Replace with your Weaviate Cloud API key
  }
);

await client.collections.create({
  name: 'Question',
  vectorizers: vectors.text2VecWeaviate(),
});

client.close(); // Close the client connection
```

**Go (v5)**

The collection also contains a configuration for the generative (RAG) integration:

- OpenAI [generative AI integrations](https://docs.weaviate.io/weaviate/model-providers/openai/generative) for retrieval augmented generation (RAG).

quickstart/2\_1\_create\_collection/main.go

```go
// Set these environment variables
// WEAVIATE_HOSTNAME            your Weaviate instance hostname
// WEAVIATE_API_KEY          your Weaviate instance API key

package main

import (
    "context"
    "fmt"
    "os"

    "github.com/weaviate/weaviate-go-client/v5/weaviate"
    "github.com/weaviate/weaviate-go-client/v5/weaviate/auth"
    "github.com/weaviate/weaviate/entities/models"
)

func main() {
    cfg := weaviate.Config{
        Host:       os.Getenv("WEAVIATE_HOSTNAME"),
        Scheme:     "https",
        AuthConfig: auth.ApiKey{Value: os.Getenv("WEAVIATE_API_KEY")},
    }

    client, err := weaviate.NewClient(cfg)
    if err != nil {
        fmt.Println(err)
    }

    // Define the collection
    classObj := &models.Class{
        Class:      "Question",
        Vectorizer: "text2vec-weaviate",
        ModuleConfig: map[string]interface{}{
            "text2vec-weaviate": map[string]interface{}{},
            "generative-openai": map[string]interface{}{},
        },
    }

    // add the collection
    err = client.Schema().ClassCreator().WithClass(classObj).Do(context.Background())
    if err != nil {
        panic(err)
    }
}
```

**Java**

```java
// Best practice: store your credentials in environment variables
String weaviateUrl = System.getenv("WEAVIATE_URL");
String weaviateApiKey = System.getenv("WEAVIATE_API_KEY");

WeaviateClient client = WeaviateClient.connectToWeaviateCloud(
    weaviateUrl, // Replace with your Weaviate Cloud URL
    weaviateApiKey // Replace with your Weaviate Cloud key
);

String collectionName = "Question";
try { client.collections.delete(collectionName); } catch (Exception ignored) {} // Clean up from any previous run
client.collections.create(
    collectionName,
    col -> col
        .vectorConfig(VectorConfig.text2vecWeaviate()) // Configure the Weaviate Embeddings integration
        .generativeModule(Generative.openai()) // Configure the OpenAI generative AI integration
);
CollectionHandle<Map<String, Object>> questions = client.collections.use(collectionName);
client.close(); // Free up resources
```

**C#**

```csharp
var questions = await client.Collections.Create(
    new CollectionCreateParams
    {
        Name = collectionName,
        Properties =
        [
            Property.Text("answer"),
            Property.Text("question"),
            Property.Text("category"),
        ],
        VectorConfig = Configure.Vector("default", v => v.Text2VecWeaviate()), // Configure the Weaviate Embeddings integration
        GenerativeConfig = Configure.Generative.OpenAI(), // Configure the OpenAI generative AI integration
    }
);
```

**Curl**

The collection also contains a configuration for the generative (RAG) integration:

- OpenAI [generative AI integrations](https://docs.weaviate.io/weaviate/model-providers/openai/generative) for retrieval augmented generation (RAG).

```bash
# Best practice: store your credentials in environment variables
# export WEAVIATE_URL="YOUR_INSTANCE_URL"  # Your Weaviate instance URL
# export WEAVIATE_API_KEY="YOUR_API_KEY"   # Your Weaviate instance API key

curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $WEAVIATE_API_KEY" \
-d '{
  "class": "Question",
  "vectorizer": "text2vec-weaviate",
  "moduleConfig": {
    "text2vec-weaviate": {},
    "generative-openai": {}
  }
}' \
"$WEAVIATE_URL/v1/schema"
```

Run this code to create the collection to which you can add data.

**Do you prefer a different setup?**

If you prefer a different model provider integration, or prefer to import your own vectors, see one of the following guides:

[Prefer a different model provider?](https://docs.weaviate.io/weaviate/model-providers): See the embedding model providers page for information on other available vectorizers, such as AWS, Cohere, Google, and many more.

[You have precomputed embeddings?](https://docs.weaviate.io/weaviate/starter-guides/custom-vectors): If you prefer to add custom vectors yourself along with the object data, see the Bring Your Own Vectors starter guide.

### 2.2 Add objects

We can now add data to our collection.

The following example:

- Loads objects, and
- Adds objects to the target collection (`Question`) with a batch import.

> [!TIP]
>
> **Batch imports**
>
> Batch imports are the most efficient way to add large amounts of data, because they send objects in groups instead of one request per object. See the [How-to: Batch import](https://docs.weaviate.io/weaviate/manage-objects/import) guide for the available methods, including [server-side batching](https://docs.weaviate.io/weaviate/manage-objects/import#server-side-batching), where the server tells the client how much data to send next.

Every import reports whether any objects failed. Check for failures in your own code to catch problems such as malformed data or a misconfigured model provider.

**Python**

quickstart\_import.py

```py
import weaviate
from weaviate.classes.init import Auth
import requests, json, os

# Best practice: store your credentials in environment variables
weaviate_url = os.environ["WEAVIATE_URL"]
weaviate_api_key = os.environ["WEAVIATE_API_KEY"]

client = weaviate.connect_to_weaviate_cloud(
    cluster_url=weaviate_url,                                    # Replace with your Weaviate Cloud URL
    auth_credentials=Auth.api_key(weaviate_api_key),             # Replace with your Weaviate Cloud key
)

resp = requests.get(
    "https://raw.githubusercontent.com/weaviate-tutorials/quickstart/main/data/jeopardy_tiny.json"
)
data = json.loads(resp.text)

questions = client.collections.use("Question")

result = questions.data.ingest(
    [
        {
            "answer": d["Answer"],
            "question": d["Question"],
            "category": d["Category"],
        }
        for d in data
    ]
)

# `errors` holds one entry per failed object, keyed by its position in the input
if result.errors:
    print(f"Number of failed imports: {len(result.errors)}")
    for index, error in result.errors.items():
        print(f"Failed object at index {index}: {error.message}")

client.close()  # Free up resources
```

`data.ingest()` returns a `BatchObjectReturn`. Read `result.errors` to check for failures. It holds one entry per failed object, keyed by its position in the input. For more, see [error handling in the Python client reference](https://docs.weaviate.io/weaviate/client-libraries/python/notes-best-practices#error-handling).

**JavaScript/TypeScript**

quickstart\_import.ts

```ts
import weaviate, { WeaviateClient } from '@weaviate/node';

// Best practice: store your credentials in environment variables
const weaviateUrl = process.env.WEAVIATE_URL as string;
const weaviateApiKey = process.env.WEAVIATE_API_KEY as string;

const client: WeaviateClient = await weaviate.connectToWeaviateCloud(
  weaviateUrl, // Replace with your Weaviate Cloud URL
  {
    authCredentials: new weaviate.ApiKey(weaviateApiKey), // Replace with your Weaviate Cloud API key
  }
);

// Load data
async function getJsonData() {
  const file = await fetch(
    'https://raw.githubusercontent.com/weaviate-tutorials/quickstart/main/data/jeopardy_tiny.json'
  );
  return file.json();
}

async function importQuestions() {
  const questions = client.collections.use('Question');
  const data = await getJsonData();

  // `ingest` imports the list using server-side batching
  const result = await questions.data.ingest(
    data.map((properties) => ({ properties }))
  );

  if (result.hasErrors) {
    console.log(`Number of failed imports: ${Object.keys(result.errors).length}`);
    // `errors` is keyed by the position of the object in the input
    for (const [index, error] of Object.entries(result.errors)) {
      console.log(`Failed object at index ${index}: ${error.message}`);
    }
  }
}

await importQuestions();

client.close(); // Close the client connection
```

`data.ingest()` returns a result object. Read `result.hasErrors` for a quick check, and `result.errors` for one entry per failed object, keyed by its position in the input.

**Go (v5)**

quickstart/2\_2\_import/main.go

```go
// Set these environment variables
// WEAVIATE_HOSTNAME            your Weaviate instance hostname
// WEAVIATE_API_KEY          your Weaviate instance API key

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "net/http"
    "os"

    "github.com/weaviate/weaviate-go-client/v5/weaviate"
    "github.com/weaviate/weaviate-go-client/v5/weaviate/auth"
    "github.com/weaviate/weaviate/entities/models"
)

func main() {
    cfg := weaviate.Config{
        Host:       os.Getenv("WEAVIATE_HOSTNAME"),
        Scheme:     "https",
        AuthConfig: auth.ApiKey{Value: os.Getenv("WEAVIATE_API_KEY")},
    }

    client, err := weaviate.NewClient(cfg)
    if err != nil {
        fmt.Println(err)
    }

    // Retrieve the data
    data, err := http.DefaultClient.Get("https://raw.githubusercontent.com/weaviate-tutorials/quickstart/main/data/jeopardy_tiny.json")
    if err != nil {
        panic(err)
    }
    defer data.Body.Close()

    // Decode the data
    var items []map[string]string
    if err := json.NewDecoder(data.Body).Decode(&items); err != nil {
        panic(err)
    }

    // convert items into a slice of models.Object
    objects := make([]*models.Object, len(items))
    for i := range items {
        objects[i] = &models.Object{
            Class: "Question",
            Properties: map[string]any{
                "category": items[i]["Category"],
                "question": items[i]["Question"],
                "answer":   items[i]["Answer"],
            },
        }
    }

    // batch write items
    batchRes, err := client.Batch().ObjectsBatcher().WithObjects(objects...).Do(context.Background())
    if err != nil {
        panic(err)
    }
    for _, res := range batchRes {
        if res.Result.Errors != nil {
            panic(res.Result.Errors.Error)
        }
    }
}
```

**Java**

```java
// Best practice: store your credentials in environment variables
String weaviateUrl = System.getenv("WEAVIATE_URL");
String weaviateApiKey = System.getenv("WEAVIATE_API_KEY");

WeaviateClient client = WeaviateClient.connectToWeaviateCloud(
    weaviateUrl, // Replace with your Weaviate Cloud URL
    weaviateApiKey // Replace with your Weaviate Cloud key
);

// Create the collection
String collectionName = "Question";
try { client.collections.delete(collectionName); } catch (Exception ignored) {} // Clean up from any previous run
client.collections.create(collectionName, col -> col
    .properties(
        Property.text("answer"),
        Property.text("question"),
        Property.text("category"))
    .vectorConfig(VectorConfig.text2vecWeaviate())); // Configure the Weaviate Embeddings integration;
// Get JSON data using HttpURLConnection
URL url = URI.create("https://raw.githubusercontent.com/weaviate-tutorials/quickstart/main/data/jeopardy_tiny.json").toURL();
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
String jsonData;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
  jsonData = reader.lines().reduce("", String::concat);
}

CollectionHandle<Map<String, Object>> questions = client.collections.use(collectionName);
List<Map<String, Object>> questionsToInsert = new ArrayList<>();

// Parse and prepare objects using org.json
new JSONArray(jsonData).forEach(item -> {
  JSONObject json = (JSONObject) item;
  Map<String, Object> properties = new HashMap<>();
  properties.put("answer", json.getString("Answer"));
  properties.put("question", json.getString("Question"));
  properties.put("category", json.getString("Category"));
  questionsToInsert.add(properties);
});

// `batch.start()` opens a server-side batch
BatchContext<Map<String, Object>> batch = questions.batch.start();
// Closing the batch sends the remaining objects and waits for the results
try (batch) {
  for (Map<String, Object> properties : questionsToInsert) {
    batch.add(WeaviateObject.<Map<String, Object>>of(o -> o.properties(properties)));
  }
}

// Check for errors
if (batch.numberOfErrors() > 0) {
  System.err.printf("Number of failed imports: %d\n", batch.numberOfErrors());
} else {
  System.out.printf("Successfully inserted %d objects.\n", questionsToInsert.size());
}

client.close(); // Free up resources
```

`batch.start()` opens a server-side batch. Closing the batch sends any remaining objects and waits for the server to report the results. Read `batch.numberOfErrors()` after the batch closes; before then, the tally is incomplete.

**C#**

```csharp
// Get JSON data using HttpClient
using var httpClient = new HttpClient();
var jsonData = await httpClient.GetStringAsync(
    "https://raw.githubusercontent.com/weaviate-tutorials/quickstart/main/data/jeopardy_tiny.json"
);

var questionsToInsert = new List<object>();

// Parse and prepare objects using System.Text.Json
var jsonObjects = JsonSerializer.Deserialize<List<Dictionary<string, JsonElement>>>(
    jsonData
);
foreach (var jsonObj in jsonObjects)
{
    questionsToInsert.Add(
        new
        {
            answer = jsonObj["Answer"].GetString(),
            question = jsonObj["Question"].GetString(),
            category = jsonObj["Category"].GetString(),
        }
    );
}

// `Batch.InsertMany` imports the list using server-side batching
var insertResponse = await questions.Batch.InsertMany(questionsToInsert);

// Check for errors
if (insertResponse.HasErrors)
{
    Console.WriteLine($"Number of failed imports: {insertResponse.Errors.Count()}");
    // `Objects` holds one entry per object; `Index` is the position of the object in the input
    foreach (var entry in insertResponse.Objects.Where(o => o.Error is not null))
    {
        Console.WriteLine($"Failed object at index {entry.Index}: {entry.Error.Message}");
    }
}
else
{
    Console.WriteLine($"Successfully inserted {insertResponse.Count} objects.");
}
```

`Batch.InsertMany()` returns a `BatchInsertResponse`. Read `HasErrors` for a quick check, `Errors` for the failures alone, and `Objects` for one entry per object. Each entry's `Index` is its position in the input, and failed entries carry an `Error`.

**Curl**

> [!NOTE]
>
> - Download the `jeopardy_tiny.json` file from [here](https://raw.githubusercontent.com/weaviate-tutorials/quickstart/main/data/jeopardy_tiny.json) before running the following script.
> - This assumes you have `jq` installed.

```bash
# Best practice: store your credentials in environment variables
# export WEAVIATE_URL="YOUR_INSTANCE_URL"  # Your Weaviate instance URL
# export WEAVIATE_API_KEY="YOUR_API_KEY"   # Your Weaviate instance API key

# Set batch size
BATCH_ENDPOINT="$WEAVIATE_URL/v1/batch/objects"
BATCH_SIZE=100

# Read the JSON file and loop through its entries
lines_processed=0
batch_data="{\"objects\": ["

cat jeopardy_tiny.json | jq -c '.[]' | while read line; do
  # Concatenate lines
  line=$(echo "$line" | jq "{class: \"Question\", properties: {answer: .Answer, question: .Question, category: .Category}}")
  if [ $lines_processed -eq 0 ]; then
    batch_data+=$line
  else
    batch_data+=",$line"
  fi

  lines_processed=$((lines_processed + 1))

  # If the batch is full, send it to the API using curl
  if [ $lines_processed -eq $BATCH_SIZE ]; then
    batch_data+="]}"

    curl -X POST "$BATCH_ENDPOINT" \
         -H "Content-Type: application/json" \
         -H "Authorization: Bearer $WEAVIATE_API_KEY" \
         -d "$batch_data"
    echo "" # Print a newline for better output formatting

    # Reset the batch data and counter
    lines_processed=0
    batch_data="{\"objects\": ["
  fi
done

# Send the remaining data (if any) to the API using curl
if [ $lines_processed -ne 0 ]; then
  batch_data+="]}"

  curl -X POST "$BATCH_ENDPOINT" \
       -H "Content-Type: application/json" \
       -H "Authorization: Bearer $WEAVIATE_API_KEY" \
       -d "$batch_data"
  echo "" # Print a newline for better output formatting
fi
```

Run this code to add the demo data.

---

## Step 3: Queries

Weaviate provides a wide range of query tools to help you find the right data. We will try a few searches here.

### 3.1 Semantic search

Semantic search finds results based on meaning. This is called `nearText` in Weaviate.

The following example searches for 2 objects whose meaning is most similar to that of `biology`.

**Python**

quickstart\_neartext\_query.py

```py
import weaviate
from weaviate.classes.init import Auth
import os, json

# Best practice: store your credentials in environment variables
weaviate_url = os.environ["WEAVIATE_URL"]
weaviate_api_key = os.environ["WEAVIATE_API_KEY"]

client = weaviate.connect_to_weaviate_cloud(
    cluster_url=weaviate_url,                                    # Replace with your Weaviate Cloud URL
    auth_credentials=Auth.api_key(weaviate_api_key),             # Replace with your Weaviate Cloud key
)

questions = client.collections.use("Question")

response = questions.query.near_text(
    query="biology",
    limit=2
)

for obj in response.objects:
    print(json.dumps(obj.properties, indent=2))

client.close()  # Free up resources
```

**JavaScript/TypeScript**

quickstart\_neartext\_query.ts

```ts
import weaviate, { WeaviateClient } from '@weaviate/node';

// Best practice: store your credentials in environment variables
const weaviateUrl = process.env.WEAVIATE_URL as string;
const weaviateApiKey = process.env.WEAVIATE_API_KEY as string;

const client: WeaviateClient = await weaviate.connectToWeaviateCloud(
  weaviateUrl, // Replace with your Weaviate Cloud URL
  {
    authCredentials: new weaviate.ApiKey(weaviateApiKey), // Replace with your Weaviate Cloud API key
  }
);

const questions = client.collections.use('Question');

const result = await questions.query.nearText('biology', {
  limit: 2,
});

result.objects.forEach((item) => {
  console.log(JSON.stringify(item.properties, null, 2));
});

client.close(); // Close the client connection
```

**Go (v5)**

quickstart/3\_1\_neartext/main.go

```go
// Set these environment variables
// WEAVIATE_HOSTNAME            your Weaviate instance hostname
// WEAVIATE_API_KEY          your Weaviate instance API key

package main

import (
    "context"
    "fmt"
    "os"

    "github.com/weaviate/weaviate-go-client/v5/weaviate"
    "github.com/weaviate/weaviate-go-client/v5/weaviate/auth"
    "github.com/weaviate/weaviate-go-client/v5/weaviate/graphql"
)

func main() {
    cfg := weaviate.Config{
        Host:       os.Getenv("WEAVIATE_HOSTNAME"),
        Scheme:     "https",
        AuthConfig: auth.ApiKey{Value: os.Getenv("WEAVIATE_API_KEY")},
    }

    client, err := weaviate.NewClient(cfg)
    if err != nil {
        fmt.Println(err)
    }

    ctx := context.Background()

    response, err := client.GraphQL().Get().
        WithClassName("Question").
        WithFields(
            graphql.Field{Name: "question"},
            graphql.Field{Name: "answer"},
            graphql.Field{Name: "category"},
        ).
        WithNearText(client.GraphQL().NearTextArgBuilder().
            WithConcepts([]string{"biology"})).
        WithLimit(2).
        Do(ctx)

    if err != nil {
        panic(err)
    }
    fmt.Printf("%v", response)
}
```

**Java**

```java
// Best practice: store your credentials in environment variables
String weaviateUrl = System.getenv("WEAVIATE_URL");
String weaviateApiKey = System.getenv("WEAVIATE_API_KEY");

WeaviateClient client = WeaviateClient.connectToWeaviateCloud(
    weaviateUrl, // Replace with your Weaviate Cloud URL
    weaviateApiKey // Replace with your Weaviate Cloud key
);

String collectionName = "Question";
var questions = client.collections.use(collectionName);

var response = questions.query.nearText("biology", q -> q.limit(2));

for (var obj : response.objects()) {
  System.out.println(obj.properties());
}

client.close(); // Free up resources
```

**C#**

```csharp
var response = await questions.Query.NearText("biology", limit: 2);

foreach (var obj in response.Objects)
{
    Console.WriteLine(JsonSerializer.Serialize(obj.Properties));
}
```

**Curl**

```bash
# Best practice: store your credentials in environment variables
# export WEAVIATE_URL="YOUR_INSTANCE_URL"    # Your Weaviate instance URL
# export WEAVIATE_API_KEY="YOUR_API_KEY"     # Your Weaviate instance API key

echo '{
  "query": "{
    Get {
      Question (
        limit: 2
        nearText: {
          concepts: [\"biology\"],
        }
      ) {
        question
        answer
        category
      }
    }
  }"
}' | tr -d "\n" | curl \
    -X POST \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $WEAVIATE_API_KEY" \
    -d @- \
    $WEAVIATE_URL/v1/graphql
```

Run this code to perform the query. Our query found entries for `DNA` and `species`.

**Example response**

```json
{
  "answer": "DNA",
  "question": "In 1953 Watson & Crick built a model of the molecular structure of this, the gene-carrying substance",
  "category": "SCIENCE"
}
{
  "answer": "species",
  "question": "2000 news: the Gunnison sage grouse isn't just another northern sage grouse, but a new one of this classification",
  "category": "SCIENCE"
}
```

If you inspect the full response, you will see that the word `biology` does not appear anywhere.

Even so, Weaviate was able to return biology-related entries. This is made possible by *vector embeddings* that capture meaning. Under the hood, semantic search is powered by vectors, or vector embeddings.

Here is a diagram showing the workflow in Weaviate.

```mermaid
flowchart LR
    Query["🔍 Search:<br> 'biology'"]

    subgraph sg1 ["Vector Search"]
        direction LR
        VS1["Convert query<br> to vector"] --> VS2["Find similar<br> vectors"]
        VS2 --> VS3["Return top<br> matches"]
    end

    subgraph sg2 ["Results"]
        R1["Most similar<br> documents"]
    end

    Query --> VS1
    VS3 --> R1

    %% Style nodes with white background and darker borders
    style Query fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style VS1 fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style VS2 fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style VS3 fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style R1 fill:#ffffff,stroke:#B9C8DF,color:#130C49

    %% Style subgraphs with brand colors
    style sg1 fill:#ffffff,stroke:#61BD73,stroke-width:2px,color:#130C49
    style sg2 fill:#ffffff,stroke:#130C49,stroke-width:2px,color:#130C49
```

> [!NOTE]
>
> **Where did the vectors come from?**
>
> Weaviate used the **Weaviate Embeddings** service to generate a vector embedding for each object during import. During the query, Weaviate similarly converted the query (`biology`) into a vector.
>
> As we mentioned above, this is optional. See [Starter Guide: Bring Your Own Vectors](https://docs.weaviate.io/weaviate/starter-guides/custom-vectors) if you would prefer to provide your own vectors.

> [!TIP]
>
> **More search types available**
>
> Weaviate is capable of many types of searches. See, for example, our how-to guides on [similarity searches](https://docs.weaviate.io/weaviate/search/similarity), [keyword searches](https://docs.weaviate.io/weaviate/search/bm25), [hybrid searches](https://docs.weaviate.io/weaviate/search/hybrid), and [filtered searches](https://docs.weaviate.io/weaviate/search/filters).

### 3.2 Retrieval augmented generation

Retrieval augmented generation (RAG), also called generative search, combines the power of generative AI models such as large language models (LLMs) with the up-to-date truthfulness of a database.

RAG works by prompting a large language model (LLM) with a combination of a *user query* and *data retrieved from a database*.

This diagram shows the RAG workflow in Weaviate.

```mermaid
flowchart LR
    subgraph sg0 ["Weaviate Query"]
        direction TB
        Search["🔍 Search:<br> 'biology'"]
        Prompt["✍️ Prompt:<br> 'Write a<br> tweet...'"]
    end

    subgraph sg1 ["Vector Search"]
        direction LR
        VS1["Convert query<br> to vector"] --> VS2["Find similar<br> vectors"]
        VS2 --> VS3["Return top<br> matches"]
    end

    subgraph sg2 ["Generation"]
        direction LR
        G1["Send<br> (results + prompt)<br> to LLM"]
        G1 --> G2["Generate<br> response"]
    end

    subgraph sg3 ["Results"]
        direction TB
        R1["Most similar<br> documents"]
        R2["Generated<br> content"]
    end

    Search --> VS1
    VS3 --> R1
    Prompt --> G1
    VS3 --> G1
    G2 --> R2

    %% Style nodes with white background and darker borders
    style Search fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style Prompt fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style VS1 fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style VS2 fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style VS3 fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style G1 fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style G2 fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style R1 fill:#ffffff,stroke:#B9C8DF,color:#130C49
    style R2 fill:#ffffff,stroke:#B9C8DF,color:#130C49

    %% Style subgraphs with brand colors
    style sg0 fill:#ffffff,stroke:#130C49,stroke-width:2px,color:#130C49
    style sg1 fill:#ffffff,stroke:#61BD73,stroke-width:2px,color:#130C49
    style sg2 fill:#ffffff,stroke:#7AD6EB,stroke-width:2px,color:#130C49
    style sg3 fill:#ffffff,stroke:#130C49,stroke-width:2px,color:#130C49
```

The following example combines the same search (for `biology`) with a prompt to generate a tweet.

**Python**

quickstart\_rag.py

```py
import os
import weaviate
from weaviate.classes.init import Auth
from weaviate.classes.generate import GenerativeConfig


# Best practice: store your credentials in environment variables
weaviate_url = os.environ["WEAVIATE_URL"]
weaviate_api_key = os.environ["WEAVIATE_API_KEY"]
openai_api_key = os.environ["OPENAI_API_KEY"]

client = weaviate.connect_to_weaviate_cloud(
    cluster_url=weaviate_url,  # Replace with your Weaviate Cloud URL
    auth_credentials=Auth.api_key(
        weaviate_api_key
    ),  # Replace with your Weaviate Cloud key
    headers={"X-OpenAI-Api-Key": openai_api_key},  # Replace with your OpenAI API key
)

questions = client.collections.use("Question")

response = questions.generate.near_text(
    query="biology",
    limit=2,
    grouped_task="Write a tweet with emojis about these facts.",
    generative_provider=GenerativeConfig.openai(),  # Configure the OpenAI generative integration for RAG
)

print(response.generative.text)  # Inspect the generated text

client.close()  # Free up resources
```

**JavaScript/TypeScript**

quickstart\_rag.ts

```ts
import weaviate, { WeaviateClient, generativeParameters } from '@weaviate/node';

// Best practice: store your credentials in environment variables
const weaviateUrl = process.env.WEAVIATE_URL as string;
const weaviateApiKey = process.env.WEAVIATE_API_KEY as string;
const openAiKey = process.env.OPENAI_API_KEY as string;

const client: WeaviateClient = await weaviate.connectToWeaviateCloud(
  weaviateUrl, // Replace with your Weaviate Cloud URL
  {
    authCredentials: new weaviate.ApiKey(weaviateApiKey), // Replace with your Weaviate Cloud API key
    headers: {
      'X-OpenAI-Api-Key': openAiKey, // Replace with your OpenAI API key
    },
  }
);

const questions = client.collections.use('Question');

const result = await questions.generate.nearText(
  'biology',
  {
    groupedTask: 'Write a tweet with emojis about these facts.',
    config: generativeParameters.openAI(),
  },
  {
    limit: 2,
  }
);

console.log(result.generative);

client.close(); // Close the client connection
```

**Go (v5)**

quickstart/3\_2\_rag/main.go

```go
// Set these environment variables
// WEAVIATE_HOSTNAME            your Weaviate instance hostname
// WEAVIATE_API_KEY          your Weaviate instance API key
// OPENAI_API_KEY           your OpenAI API key

package main

import (
    "context"
    "fmt"
    "os"

    "github.com/weaviate/weaviate-go-client/v5/weaviate"
    "github.com/weaviate/weaviate-go-client/v5/weaviate/auth"
    "github.com/weaviate/weaviate-go-client/v5/weaviate/graphql"
)

func main() {
    cfg := weaviate.Config{
        Host:       os.Getenv("WEAVIATE_HOSTNAME"),
        Scheme:     "https",
        AuthConfig: auth.ApiKey{Value: os.Getenv("WEAVIATE_API_KEY")},
        Headers: map[string]string{
            "X-OpenAI-Api-Key": os.Getenv("OPENAI_API_KEY"),
        },
    }

    client, err := weaviate.NewClient(cfg)
    if err != nil {
        fmt.Println(err)
    }

    ctx := context.Background()

    generatePrompt := "Write a tweet with emojis about these facts."

    gs := graphql.NewGenerativeSearch().GroupedResult(generatePrompt)

    response, err := client.GraphQL().Get().
        WithClassName("Question").
        WithFields(
            graphql.Field{Name: "question"},
            graphql.Field{Name: "answer"},
            graphql.Field{Name: "category"},
        ).
        WithGenerativeSearch(gs).
        WithNearText(client.GraphQL().NearTextArgBuilder().
            WithConcepts([]string{"biology"})).
        WithLimit(2).
        Do(ctx)

    if err != nil {
        panic(err)
    }
    fmt.Printf("%v", response)
}
```

**Java**

```java
// Best practice: store your credentials in environment variables
String weaviateUrl = System.getenv("WEAVIATE_URL");
String weaviateApiKey = System.getenv("WEAVIATE_API_KEY");
String openaiApiKey = System.getenv("OPENAI_API_KEY");

WeaviateClient client = WeaviateClient.connectToWeaviateCloud(
    weaviateUrl, // Replace with your Weaviate Cloud URL
    weaviateApiKey, // Replace with your Weaviate Cloud key
    config -> config.setHeaders(
        Map.of("X-OpenAI-Api-Key", openaiApiKey)) // Replace with your OpenAI API key
);

CollectionHandle<Map<String, Object>> questions = client.collections.use("Question");

var response = questions.generate.nearText(
    "biology",
    // Query configuration (nearText and limit)
    q -> q.limit(2),
    // Generative configuration (the RAG task)
    g -> g.groupedTask(
        "Write a tweet with emojis about these facts.",
        c -> c.generativeProvider(GenerativeProvider.openai(o -> o))));

// Use `.generative()` to access the generated text
System.out.println(response.generative().text());

client.close(); // Free up resources
```

**C#**

```csharp
var ragResponse = await questions.Generate.NearText(
    "biology",
    limit: 2,
    groupedTask: new GroupedTask("Write a tweet with emojis about these facts."),
    provider: new Providers.OpenAI() { }
);

// Inspect the results
Console.WriteLine(JsonSerializer.Serialize(ragResponse.Generative.Values));
```

**Curl**

```bash
# Best practice: store your credentials in environment variables
# export WEAVIATE_URL="YOUR_INSTANCE_URL"    # Your Weaviate instance URL
# export WEAVIATE_API_KEY="YOUR_API_KEY"     # Your Weaviate instance API key
# export OPENAI_API_KEY="YOUR_API_KEY"       # Your OpenAI API key

echo '{
  "query": "{
    Get {
      Question (
        limit: 2
        nearText: {
          concepts: [\"biology\"],
        }
      ) {
        question
        answer
        category
        _additional {
          generate(
            groupedResult: {
              task: \"\"\"
                Write a tweet with emojis about these facts.
              \"\"\"
            }
          ) {
            groupedResult
            error
          }
        }
      }
    }
  }"
}' | tr -d "\n" | curl \
    -X POST \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $WEAVIATE_API_KEY" \
    -H "X-OpenAI-Api-Key: $OPENAI_API_KEY" \
    -d @- \
    $WEAVIATE_URL/v1/graphql
```

> [!NOTE]
>
> **OpenAI API key in the header**
>
> Note that this code includes an additional header for the OpenAI API key. Weaviate uses this key to access the OpenAI generative AI model and perform retrieval augmented generation (RAG).

Run this code to perform the query. Here is one possible response (your response will likely be different).

```text
🧬 In 1953 Watson & Crick built a model of the molecular structure of DNA, the gene-carrying substance! 🧬🔬

🦢 2000 news: the Gunnison sage grouse isn't just another northern sage grouse, but a new species! 🦢🌿 #ScienceFacts #DNA #SpeciesClassification
```

The response should be new, yet familiar. This is because you have seen the entries above for `DNA` and `species` in the [semantic search](https://docs.weaviate.io/weaviate/tutorials/quick-tour-of-weaviate#semantic-search) section.

The power of RAG comes from the ability to transform your own data. Weaviate helps you in this journey by making it easy to perform a combined search & generation in just a few lines of code.

---

## Recap

In this quickstart guide, you:

- Created a free cluster on Weaviate Cloud.

- Defined a collection and added data.

- Performed queries, including:

  - Semantic search, and
  - Retrieval augmented generation.

Where to go next is up to you. We include some suggested steps and resources below.

---
