> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cyborg.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Add Items to an Encrypted Index

Once you have created or loaded an encrypted index, you can add items to it. To do this, you can use the `upsert()` function:

<CodeGroup>
  ```python Python icon="python" theme={null}
  # Items to add to the encrypted index
  items = [
      {"id": "item_1", "vector": [0.1, 0.2, 0.3, 0.4]},
      {"id": "item_2", "vector": [0.5, 0.6, 0.7, 0.8]},
      {"id": "item_3", "vector": [0.9, 0.10, 0.11, 0.12]}
  ]

  # Add items to the encrypted index
  index.upsert(items)
  ```

  ```cpp C++ icon="brackets-curly" theme={null}
  // Items to add to the encrypted index
  std::vector<std::string> ids = {"item_1", "item_2", "item_3"};
  cyborg::Array2D<float> vectors{{0.1, 0.2, 0.3, 0.4}, {0.5, 0.6, 0.7, 0.8}, {0.9, 0.10, 0.11, 0.12}};

  // Add items to the encrypted index (index_key implicitly builds the KeyContext)
  index->Upsert(ids, vectors, /*contents=*/{}, /*metadata=*/{}, index_key);
  ```
</CodeGroup>

For more info on `Array2D` in C++, see the [API Reference](../../cpp/types#array2d).

<Note>In Python, the common path reuses the key supplied at `create_index`/`load_index`, so `upsert()` takes no key. In C++ every key-bearing method takes a trailing `KeyContext`, which constructs implicitly from a bare 32-byte KEK — so `index->Upsert(..., index_key)` is the common path. You can also pass `index_key=` (and `user_id=` for an RBAC user) per operation to override the key, which is required in stateless/service deployments that reload the index per request.</Note>

## Adding Items with Contents

It's also possible to store item contents alongside vectors. To do this, include `contents` to the `upsert()` call.

For Python, the contents field accepts both strings and bytes. For C++, the contents field only accepts bytes. All contents are encoded to bytes and encrypted before storage using the index key, and will be returned as bytes when retrieved with `get()`.

<CodeGroup>
  ```python Python icon="python" theme={null}
  # Items to add to the encrypted index
  items = [
      {"id": "item_1", "vector": [0.1, 0.2, 0.3, 0.4], "contents": "Hello!"},
      {"id": "item_2", "vector": [0.5, 0.6, 0.7, 0.8], "contents": "World!"},
      {"id": "item_3", "vector": [0.9, 0.10, 0.11, 0.12], "contents": "Cyborg!"}
  ]

  # Add items to the encrypted index
  index.upsert(items)
  ```

  ```cpp C++ icon="brackets-curly" theme={null}
  // Items to add to the encrypted index
  std::vector<std::string> ids = {"item_1", "item_2", "item_3"};
  cyborg::Array2D<float> vectors{{0.1, 0.2, 0.3, 0.4}, {0.5, 0.6, 0.7, 0.8}, {0.9, 0.10, 0.11, 0.12}};
  std::vector<std::vector<uint8_t>> contents = {
      std::vector<uint8_t>{'H', 'e', 'l', 'l', 'o', '!'},
      std::vector<uint8_t>{'W', 'o', 'r', 'l', 'd', '!'},
      std::vector<uint8_t>{'C', 'y', 'b', 'o', 'r', 'g', '!'}
  };

  // Add items to the encrypted index
  index->Upsert(ids, vectors, contents, /*metadata=*/{}, index_key);
  ```
</CodeGroup>

## Adding Items with Metadata

CyborgDB also supports metadata storage, retrieval and filtering. To add metadata to an item, include `metadata` in the `upsert()` call.

All metadata fields will be encrypted using the index key.

<CodeGroup>
  ```python Python icon="python" theme={null}
  # Items to add to the encrypted index
  items = [
      {"id": "item_1", "vector": [0.1, 0.2, 0.3, 0.4], "metadata": {"name": "Alice", "age": 30}},
      {"id": "item_2", "vector": [0.5, 0.6, 0.7, 0.8], "metadata": {"name": "Bob", "age": 40}},
      {"id": "item_3", "vector": [0.9, 0.10, 0.11, 0.12], "metadata": {"name": "Charlie", "age": 50}}
  ]

  # Add items to the encrypted index
  index.upsert(items)
  ```

  ```cpp C++ icon="brackets-curly" theme={null}
  // Items to add to the encrypted index
  std::vector<std::string> ids = {"item_1", "item_2", "item_3"};
  cyborg::Array2D<float> vectors{{0.1, 0.2, 0.3, 0.4}, {0.5, 0.6, 0.7, 0.8}, {0.9, 0.10, 0.11, 0.12}};
  std::vector<std::string> metadata = {
      R"({"name": "Alice", "age": 30})",
      R"({"name": "Bob", "age": 40})",
      R"({"name": "Charlie", "age": 50})"
  };

  // Add items to the encrypted index
  index->Upsert(ids, vectors, /*contents=*/{}, metadata, index_key);
  ```
</CodeGroup>

For more info on metadata storage and filtering, see [Metadata Filtering](./metadata-filtering).

## Automatic Embedding Generation

<Tip>This feature is only available in Python. To use it, use `pip install cyborgdb-core[embeddings]`</Tip>

If you provided an `embedding_model` during index creation, you can automatically generate embeddings for items by providing `contents` to the `upsert()` call:

```python Python icon="python" theme={null}
# ... index creation and embedding model setup
embedding_model = "all-MiniLM-L6-v2"
index = client.create_index(
    index_name="my_index",
    index_key=index_key,
    embedding_model=embedding_model
)

# Items to add to the encrypted index
items = [
    {"id": "item_1", "contents": "Hello, World!"},
    {"id": "item_2", "contents": "Hello, Cyborg!"}
]

# Add items to the encrypted index
index.upsert(items)
```

In this example, the `embedding_model` will automatically generate embeddings for the `contents` field. Note that `contents` must be a string. It will also be converted to `bytes` for encrypted item storage.

This feature uses [`sentence-transformers`](https://www.sbert.net/) for embedding generation. You can use any model from the [HuggingFace Model Hub](https://huggingface.co/models) that is compatible with `sentence-transformers`.

## API Reference

For more information on adding items to an encrypted index, refer to the API reference:

<CardGroup cols={2}>
  <Card title="Python API Reference" href="../../python/encrypted-index/upsert" icon="python">
    API reference for `upsert()` in Python
  </Card>

  <Card title="C++ API Reference" href="../../cpp/encrypted-index/upsert" icon="brackets-curly">
    API reference for `Upsert()` in C++
  </Card>
</CardGroup>
