Skip to main content
Go to documentation:
⌘U
Weaviate Database

Develop AI applications using Weaviate's APIs and tools

Deploy

Deploy, configure, and maintain Weaviate Database

Query Agent

Run agentic search over your Weaviate Cloud collections

Weaviate Cloud

Manage and scale Weaviate in the cloud

Engram

Persistent memory for LLM agents and applications

Additional resources

Integrations
Weaviate Academy

Need help?

Weaviate LogoAsk AI Assistant⌘K
Support
Community Forum
Contributor guide

Migrate data

Follow these examples to migrate data manually when using a backup is not possible. They cover all permutations between:

  • a single-tenancy collection (Collection), and
  • a tenant in a multi-tenancy collection (Tenant).
Additional information

The examples use two different Weaviate instances, exposed through different ports. The same process can be used for two different instances as well.

Cross-references in Weaviate are properties. As such, you can retrieve cross-reference as a part of the object.

What about cross-references?

These scripts should migrate cross-references as well.


Cross-references are properties. As such, these cursor-based exports will include them. During restoration, restore the cross-referenced (i.e. "to") object first, then the object that contains the cross-reference (i.e. "from" object).

Collection → Collection​

Step 1: Create the target collection(s)​

Create a collection (e.g. WineReview) at the target instance, matching the collection (e.g. WineReview) at the source instance.

py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
import weaviate
import weaviate.classes as wvc
from weaviate.collections import Collection
from weaviate.client import WeaviateClient

client_src = weaviate.connect_to_local(
headers={
"X-OpenAI-Api-Key": os.getenv("OPENAI_API_KEY")
}
)

client_tgt = weaviate.connect_to_local(
port=8090,
grpc_port=50061,
headers={
"X-OpenAI-Api-Key": os.getenv("OPENAI_API_KEY")
}
)

def create_collection(client_in: WeaviateClient, collection_name: str, enable_mt=False):

reviews = client_in.collections.create(
name=collection_name,
multi_tenancy_config=wvc.config.Configure.multi_tenancy(enabled=enable_mt),
# Additional settings not shown
)

return reviews


reviews_tgt = create_collection(client_tgt, "WineReview", enable_mt=False)
import weaviate, { Collection, WeaviateClient } from '@weaviate/node'

let client_src: WeaviateClient,client_tgt: WeaviateClient;
let reviews_mt_tgt, reviews_mt_src;
let reviews_tgt, reviews_src;

client_src = await weaviate.connectToLocal({
})

client_tgt = await weaviate.connectToLocal({
port: 8090,
grpcPort: 50061,
})

async function createCollection(clientIn: WeaviateClient, collectionName: string, enableMt: boolean) {
let reviews = clientIn.collections.create({
name: collectionName,
multiTenancy: {
enabled: enableMt
},
// Additional settings not shown
})

return reviews
}

reviews_tgt = await createCollection(client_tgt, "WineReview", false)
  private static CollectionHandle<Map<String, Object>> createCollection(
WeaviateClient clientIn, String collectionName, boolean enableMt)
throws IOException {
clientIn.collections.create(collectionName,
col -> col.multiTenancy(c -> c.enabled(enableMt))
// Additional settings not shown
.vectorConfig(VectorConfig.text2vecTransformers())
.generativeModule(Generative.cohere())
.properties(Property.text("review_body"), Property.text("title"),
Property.text("country"), Property.integer("points"),
Property.number("price")));

return clientIn.collections.use(collectionName);
}

void createCollectionToCollection() throws IOException {
createCollection(clientTgt, "WineReview", false);
}
private static async Task<CollectionClient> CreateCollection(
WeaviateClient clientIn,
string collectionName,
bool enableMt
)
{
return await clientIn.Collections.Create(
new CollectionCreateParams
{
Name = collectionName,
MultiTenancyConfig = new MultiTenancyConfig { Enabled = enableMt },
VectorConfig = Configure.Vector("default", v => v.Text2VecTransformers()),
Properties =
[
Property.Text("review_body"),
Property.Text("title"),
Property.Text("country"),
Property.Int("points"),
Property.Number("price"),
],
}
);
}

private async Task CreateCollectionToCollection()
{
await CreateCollection(clientTgt, "WineReview", false);
}

Step 2: Migrate the data​

Migrate:

  • The source collection data in the client_src instance
  • to target collection in the client_tgt instance
py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
def migrate_data(collection_src: Collection, collection_tgt: Collection):

with collection_tgt.batch.fixed_size(batch_size=100) as batch:
for q in tqdm(collection_src.iterator(include_vector=True)):
batch.add_object(
properties=q.properties,
vector={
"default": q.vector["default"],
},
uuid=q.uuid
)

return True


reviews_src = client_src.collections.get("WineReview")
reviews_tgt = client_tgt.collections.get("WineReview")

migrate_data(reviews_src, reviews_tgt)

client_src.close()
client_tgt.close()
let reviews_tgt, reviews_src;
reviews_src = client_src.collections.use("WineReview")
reviews_tgt = client_tgt.collections.use("WineReview")

let maxItems = await reviews_src.length()
let counter: number = 0

async function migrateData(collection_src: Collection, collection_tgt: Collection) {
let itemsToInsert = []
const promises = []

for await (const item of collection_src.iterator({ includeVector: true })) {
// Check if we've reached the maximum items
if (counter >= maxItems) {
console.log(`Reached maximum items limit of ${maxItems}`);
break;
}

counter++;
if (counter % 500 == 0)
console.log(`Import: ${counter}`)

let objectToInsert = {
properties: item.properties,
vectors: item.vectors.default,
uuid: item.uuid,
}

// Add object to batching array
itemsToInsert.push(objectToInsert)

if (itemsToInsert.length == 500 || counter == maxItems) {
try {
const response = await collection_tgt.data.insertMany(itemsToInsert);

if (response.hasErrors) {
throw new Error("Error in batch import!");
}

console.log(`Successfully imported batch of ${itemsToInsert.length} items`);
itemsToInsert = [];
} catch (error) {
console.error('Error importing batch:', error);
}
}
}

}

migrateData(reviews_src, reviews_tgt)

client_src.close()
client_tgt.close()
  private void migrateData(CollectionHandle<Map<String, Object>> collectionSrc,
CollectionHandle<Map<String, Object>> collectionTgt) {
System.out.println("Starting data migration...");
List<WeaviateObject<Map<String, Object>>> sourceObjects = StreamSupport
.stream(collectionSrc.paginate(p -> p.includeVector()).spliterator(),
false)
.map(readObj -> WeaviateObject
.<Map<String, Object>>of(c -> c.properties(readObj.properties())
.uuid(readObj.uuid())
.vectors(readObj.vectors())))
.collect(Collectors.toList());

collectionTgt.data.insertMany(sourceObjects);

System.out.println("Data migration complete.");
}

void testCollectionToCollection() throws IOException {
createCollectionToCollection();

var reviewsSrc = clientSrc.collections.use("WineReview");
var reviewsTgt = clientTgt.collections.use("WineReview");
migrateData(reviewsSrc, reviewsTgt);

}
private async Task MigrateData<T>(
CollectionClient collectionSrc,
CollectionClient collectionTgt
)
{
Console.WriteLine("Starting data migration...");

// Fetch source objects
var response = await collectionSrc.Query.FetchObjects(limit: 10000, includeVectors: true);

// Map to Strong Type List
var sourceObjects = new List<T>();
foreach (var obj in response.Objects)
{
// Deserialize the inner properties Dictionary to the POCO type
var json = JsonSerializer.Serialize(obj.Properties);
var typedObj = JsonSerializer.Deserialize<T>(json);
if (typedObj != null)
{
sourceObjects.Add(typedObj);
}
}

// InsertMany using Strong Types
await collectionTgt.Data.InsertMany(sourceObjects.ToArray());

Console.WriteLine($"Data migration complete. Migrated {sourceObjects.Count} objects.");
}

public async Task TestCollectionToCollection()
{
await CreateCollectionToCollection();

var reviewsSrc = clientSrc.Collections.Use("WineReview");
var reviewsTgt = clientTgt.Collections.Use("WineReview");

// Pass the Type to the generic method
}

Collection → Tenant​

Step 1: Create the target collection(s)​

Create a collection (e.g. WineReview) at the target instance, matching the collection (e.g. WineReview) at the source instance, and enable multi-tenancy for the target collection.

py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
import weaviate
import weaviate.classes as wvc
from weaviate.collections import Collection
from weaviate.client import WeaviateClient

client_src = weaviate.connect_to_local(
headers={
"X-OpenAI-Api-Key": os.getenv("OPENAI_API_KEY")
}
)

client_tgt = weaviate.connect_to_local(
port=8090,
grpc_port=50061,
headers={
"X-OpenAI-Api-Key": os.getenv("OPENAI_API_KEY")
}
)

def create_collection(client_in: WeaviateClient, collection_name: str, enable_mt=False):

reviews = client_in.collections.create(
name=collection_name,
multi_tenancy_config=wvc.config.Configure.multi_tenancy(enabled=enable_mt),
# Additional settings not shown
)

return reviews


reviews_mt_tgt = create_collection(client_tgt, "WineReviewMT", enable_mt=True)
import weaviate, { Collection, WeaviateClient } from '@weaviate/node'

let client_src: WeaviateClient,client_tgt: WeaviateClient;
let reviews_mt_tgt, reviews_mt_src;

client_src = await weaviate.connectToLocal({
})

client_tgt = await weaviate.connectToLocal({
port: 8090,
grpcPort: 50061,
})

async function createCollection(clientIn: WeaviateClient, collectionName: string, enableMt: boolean) {
let reviews = clientIn.collections.create({
name: collectionName,
multiTenancy: {
enabled: enableMt
},
// Additional settings not shown
})

return reviews
}

reviews_mt_tgt = createCollection(client_tgt, "WineReviewMT", true)
  private static CollectionHandle<Map<String, Object>> createCollection(
WeaviateClient clientIn, String collectionName, boolean enableMt)
throws IOException {
clientIn.collections.create(collectionName,
col -> col.multiTenancy(c -> c.enabled(enableMt))
// Additional settings not shown
.vectorConfig(VectorConfig.text2vecTransformers())
.generativeModule(Generative.cohere())
.properties(Property.text("review_body"), Property.text("title"),
Property.text("country"), Property.integer("points"),
Property.number("price")));

return clientIn.collections.use(collectionName);
}

void createCollectionToTenant() throws IOException {
createCollection(clientTgt, "WineReviewMT", true);
}
private static async Task<CollectionClient> CreateCollection(
WeaviateClient clientIn,
string collectionName,
bool enableMt
)
{
return await clientIn.Collections.Create(
new CollectionCreateParams
{
Name = collectionName,
MultiTenancyConfig = new MultiTenancyConfig { Enabled = enableMt },
VectorConfig = Configure.Vector("default", v => v.Text2VecTransformers()),
Properties =
[
Property.Text("review_body"),
Property.Text("title"),
Property.Text("country"),
Property.Int("points"),
Property.Number("price"),
],
}
);
}

private async Task CreateCollectionToTenant()
{
await CreateCollection(clientTgt, "WineReviewMT", true);
}

Step 2: Create the tenant(s)​

Add tenants at the target instance before adding data objects.

py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
tenants_tgt = [wvc.tenants.Tenant(name="tenantA"), wvc.tenants.Tenant(name="tenantB")]

reviews_mt_tgt = client_tgt.collections.get("WineReviewMT")
reviews_mt_tgt.tenants.create(tenants_tgt)
let tenantsTgt = [
{ name: 'tenantA'},
{ name: 'tenantB'}
]

reviews_mt_tgt = client_tgt.collections.use("WineReviewMT")
reviews_mt_tgt.tenants.create(tenantsTgt)
  void createTenants() throws IOException {
var reviewsMtTgt = clientTgt.collections.use("WineReviewMT");

var tenantsTgt =
List.of(Tenant.active("tenantA"), Tenant.active("tenantB"));
reviewsMtTgt.tenants.create(tenantsTgt);
}
private async Task CreateTenants()
{
var reviewsMtTgt = clientTgt.Collections.Use("WineReviewMT");

var tenantsTgt = new[]
{
new Tenant { Name = "tenantA" },
new Tenant { Name = "tenantB" },
};
await reviewsMtTgt.Tenants.Create(tenantsTgt);
}

Step 3: Migrate the data​

Migrate:

  • The source collection data in the client_src instance
  • to target tenant data from target collection in the client_tgt instance
py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
def migrate_data(collection_src: Collection, collection_tgt: Collection):

with collection_tgt.batch.fixed_size(batch_size=100) as batch:
for q in tqdm(collection_src.iterator(include_vector=True)):
batch.add_object(
properties=q.properties,
vector={
"default": q.vector["default"],
},
uuid=q.uuid
)

return True


reviews_src = client_src.collections.get("WineReview")
reviews_mt_tgt = client_tgt.collections.get("WineReviewMT")
reviews_tgt_tenant_a = reviews_mt_tgt.with_tenant(tenants_tgt[0].name)

migrate_data(reviews_src, reviews_tgt_tenant_a)

client_src.close()
client_tgt.close()
let reviews_tgt, reviews_src;

reviews_src = client_src.collections.use("WineReview")
reviews_mt_tgt = client_tgt.collections.use("WineReviewMT")

let maxItems = await reviews_src.length()
let counter: number = 0

async function migrateData(collection_src: Collection, collection_tgt: Collection) {
let itemsToInsert = []
const promises = []

for await (const item of collection_src.iterator({ includeVector: true })) {
// Check if we've reached the maximum items
if (counter >= maxItems) {
console.log(`Reached maximum items limit of ${maxItems}`);
break;
}

counter++;
if (counter % 500 == 0)
console.log(`Import: ${counter}`)

let objectToInsert = {
properties: item.properties,
vectors: item.vectors.default,
uuid: item.uuid,
}

// Add object to batching array
itemsToInsert.push(objectToInsert)

if (itemsToInsert.length == 500 || counter == maxItems) {
try {
const response = await collection_tgt.data.insertMany(itemsToInsert);

if (response.hasErrors) {
throw new Error("Error in batch import!");
}

console.log(`Successfully imported batch of ${itemsToInsert.length} items`);
itemsToInsert = [];
} catch (error) {
console.error('Error importing batch:', error);
}
}
}

}

let reviews_tgt_tenant_a = reviews_mt_tgt.withTenant(tenantsTgt[0].name)
migrateData(reviews_src, reviews_tgt_tenant_a)

client_src.close()
client_tgt.close()
  private void migrateData(CollectionHandle<Map<String, Object>> collectionSrc,
CollectionHandle<Map<String, Object>> collectionTgt) {
System.out.println("Starting data migration...");
List<WeaviateObject<Map<String, Object>>> sourceObjects = StreamSupport
.stream(collectionSrc.paginate(p -> p.includeVector()).spliterator(),
false)
.map(readObj -> WeaviateObject
.<Map<String, Object>>of(c -> c.properties(readObj.properties())
.uuid(readObj.uuid())
.vectors(readObj.vectors())))
.collect(Collectors.toList());

collectionTgt.data.insertMany(sourceObjects);

System.out.println("Data migration complete.");
}

void testCollectionToTenant() throws IOException {
createCollectionToTenant();
createTenants();

var reviewsMtTgt = clientTgt.collections.use("WineReviewMT");
var reviewsSrc = clientSrc.collections.use("WineReview");

var reviewsTgtTenantA = reviewsMtTgt.withTenant("tenantA");

migrateData(reviewsSrc, reviewsTgtTenantA);
}
private async Task MigrateData<T>(
CollectionClient collectionSrc,
CollectionClient collectionTgt
)
{
Console.WriteLine("Starting data migration...");

// Fetch source objects
var response = await collectionSrc.Query.FetchObjects(limit: 10000, includeVectors: true);

// Map to Strong Type List
var sourceObjects = new List<T>();
foreach (var obj in response.Objects)
{
// Deserialize the inner properties Dictionary to the POCO type
var json = JsonSerializer.Serialize(obj.Properties);
var typedObj = JsonSerializer.Deserialize<T>(json);
if (typedObj != null)
{
sourceObjects.Add(typedObj);
}
}

// InsertMany using Strong Types
await collectionTgt.Data.InsertMany(sourceObjects.ToArray());

Console.WriteLine($"Data migration complete. Migrated {sourceObjects.Count} objects.");
}

public async Task TestCollectionToTenant()
{
await CreateCollectionToTenant();
await CreateTenants();

var reviewsMtTgt = clientTgt.Collections.Use("WineReviewMT");
var reviewsSrc = clientSrc.Collections.Use("WineReview");

var reviewsTgtTenantA = reviewsMtTgt.WithTenant("tenantA");

await MigrateData<WineReviewModel>(reviewsSrc, reviewsTgtTenantA);
}

Tenant → Collection​

Step 1: Create the target collection(s)​

Create a collection (e.g. WineReview) at the target instance, matching the collection (e.g. WineReview) at the source instance, and enable multi-tenancy for the target collection.

py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
import weaviate
import weaviate.classes as wvc
from weaviate.collections import Collection
from weaviate.client import WeaviateClient

client_src = weaviate.connect_to_local(
headers={
"X-OpenAI-Api-Key": os.getenv("OPENAI_API_KEY")
}
)

client_tgt = weaviate.connect_to_local(
port=8090,
grpc_port=50061,
headers={
"X-OpenAI-Api-Key": os.getenv("OPENAI_API_KEY")
}
)

def create_collection(client_in: WeaviateClient, collection_name: str, enable_mt=False):

reviews = client_in.collections.create(
name=collection_name,
multi_tenancy_config=wvc.config.Configure.multi_tenancy(enabled=enable_mt),
# Additional settings not shown
)

return reviews


reviews_tgt = create_collection(client_tgt, "WineReview", enable_mt=False)
import weaviate, { Collection, WeaviateClient } from '@weaviate/node'

let client_src: WeaviateClient,client_tgt: WeaviateClient;
let reviews_mt_tgt, reviews_mt_src;

client_src = await weaviate.connectToLocal({
})

client_tgt = await weaviate.connectToLocal({
port: 8090,
grpcPort: 50061,
})

async function createCollection(clientIn: WeaviateClient, collectionName: string, enableMt: boolean) {
let reviews = clientIn.collections.create({
name: collectionName,
multiTenancy: {
enabled: enableMt
},
// Additional settings not shown
})

return reviews
}

reviews_tgt = await createCollection(client_tgt, "WineReview", false)
  private static CollectionHandle<Map<String, Object>> createCollection(
WeaviateClient clientIn, String collectionName, boolean enableMt)
throws IOException {
clientIn.collections.create(collectionName,
col -> col.multiTenancy(c -> c.enabled(enableMt))
// Additional settings not shown
.vectorConfig(VectorConfig.text2vecTransformers())
.generativeModule(Generative.cohere())
.properties(Property.text("review_body"), Property.text("title"),
Property.text("country"), Property.integer("points"),
Property.number("price")));

return clientIn.collections.use(collectionName);
}

void createTenantToCollection() throws IOException {
createCollection(clientTgt, "WineReview", false);
}
private static async Task<CollectionClient> CreateCollection(
WeaviateClient clientIn,
string collectionName,
bool enableMt
)
{
return await clientIn.Collections.Create(
new CollectionCreateParams
{
Name = collectionName,
MultiTenancyConfig = new MultiTenancyConfig { Enabled = enableMt },
VectorConfig = Configure.Vector("default", v => v.Text2VecTransformers()),
Properties =
[
Property.Text("review_body"),
Property.Text("title"),
Property.Text("country"),
Property.Int("points"),
Property.Number("price"),
],
}
);
}

private async Task CreateTenantToCollection()
{
await CreateCollection(clientTgt, "WineReview", false);
}

Step 2: Migrate the data​

Migrate:

  • The source tenant data from source collection in the client_src instance
  • to target collection in the client_tgt instance
py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
def migrate_data(collection_src: Collection, collection_tgt: Collection):

with collection_tgt.batch.fixed_size(batch_size=100) as batch:
for q in tqdm(collection_src.iterator(include_vector=True)):
batch.add_object(
properties=q.properties,
vector={
"default": q.vector["default"],
},
uuid=q.uuid
)

return True


reviews_src = client_src.collections.get("WineReviewMT")
reviews_src_tenant_a = reviews_src.with_tenant("tenantA")
reviews_tgt = client_tgt.collections.get("WineReview")

migrate_data(reviews_src_tenant_a, reviews_tgt)

client_src.close()
client_tgt.close()
let reviews_tgt, reviews_src;

let maxItems = await reviews_src.length()
let counter: number = 0

async function migrateData(collection_src: Collection, collection_tgt: Collection) {
let itemsToInsert = []
const promises = []

for await (const item of collection_src.iterator({ includeVector: true })) {
// Check if we've reached the maximum items
if (counter >= maxItems) {
console.log(`Reached maximum items limit of ${maxItems}`);
break;
}

counter++;
if (counter % 500 == 0)
console.log(`Import: ${counter}`)

let objectToInsert = {
properties: item.properties,
vectors: item.vectors.default,
uuid: item.uuid,
}

// Add object to batching array
itemsToInsert.push(objectToInsert)

if (itemsToInsert.length == 500 || counter == maxItems) {
try {
const response = await collection_tgt.data.insertMany(itemsToInsert);

if (response.hasErrors) {
throw new Error("Error in batch import!");
}

console.log(`Successfully imported batch of ${itemsToInsert.length} items`);
itemsToInsert = [];
} catch (error) {
console.error('Error importing batch:', error);
}
}
}

}

let reviews_src_tenant_a;

reviews_src = client_src.collections.use("WineReviewMT")
reviews_src_tenant_a = reviews_src.withTenant("tenantA")
reviews_tgt = client_tgt.collections.use("WineReview")

migrateData(reviews_src_tenant_a, reviews_tgt)

client_src.close()
client_tgt.close()
  private void migrateData(CollectionHandle<Map<String, Object>> collectionSrc,
CollectionHandle<Map<String, Object>> collectionTgt) {
System.out.println("Starting data migration...");
List<WeaviateObject<Map<String, Object>>> sourceObjects = StreamSupport
.stream(collectionSrc.paginate(p -> p.includeVector()).spliterator(),
false)
.map(readObj -> WeaviateObject
.<Map<String, Object>>of(c -> c.properties(readObj.properties())
.uuid(readObj.uuid())
.vectors(readObj.vectors())))
.collect(Collectors.toList());

collectionTgt.data.insertMany(sourceObjects);

System.out.println("Data migration complete.");
}

void testTenantToCollection() throws IOException {
createTenantToCollection();

var reviewsSrc = clientSrc.collections.use("WineReviewMT");
var reviewsTgt = clientTgt.collections.use("WineReview");
var reviewsSrcTenantA = reviewsSrc.withTenant("tenantA");
migrateData(reviewsSrcTenantA, reviewsTgt);

}
private async Task MigrateData<T>(
CollectionClient collectionSrc,
CollectionClient collectionTgt
)
{
Console.WriteLine("Starting data migration...");

// Fetch source objects
var response = await collectionSrc.Query.FetchObjects(limit: 10000, includeVectors: true);

// Map to Strong Type List
var sourceObjects = new List<T>();
foreach (var obj in response.Objects)
{
// Deserialize the inner properties Dictionary to the POCO type
var json = JsonSerializer.Serialize(obj.Properties);
var typedObj = JsonSerializer.Deserialize<T>(json);
if (typedObj != null)
{
sourceObjects.Add(typedObj);
}
}

// InsertMany using Strong Types
await collectionTgt.Data.InsertMany(sourceObjects.ToArray());

Console.WriteLine($"Data migration complete. Migrated {sourceObjects.Count} objects.");
}

public async Task TestTenantToCollection()
{
await CreateTenantToCollection();

var reviewsSrc = clientSrc.Collections.Use("WineReviewMT");
var reviewsTgt = clientTgt.Collections.Use("WineReview");
var reviewsSrcTenantA = reviewsSrc.WithTenant("tenantA");

await MigrateData<WineReviewModel>(reviewsSrcTenantA, reviewsTgt);

}

Tenant → Tenant​

Step 1: Create the target collection(s)​

Create a collection (e.g. WineReview) at the target instance, matching the collection (e.g. WineReview) at the source instance including enabling multi-tenancy.

py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
import weaviate
import weaviate.classes as wvc
from weaviate.collections import Collection
from weaviate.client import WeaviateClient

client_src = weaviate.connect_to_local(
headers={
"X-OpenAI-Api-Key": os.getenv("OPENAI_API_KEY")
}
)

client_tgt = weaviate.connect_to_local(
port=8090,
grpc_port=50061,
headers={
"X-OpenAI-Api-Key": os.getenv("OPENAI_API_KEY")
}
)

def create_collection(client_in: WeaviateClient, collection_name: str, enable_mt=False):

reviews = client_in.collections.create(
name=collection_name,
multi_tenancy_config=wvc.config.Configure.multi_tenancy(enabled=enable_mt),
# Additional settings not shown
)

return reviews


reviews_mt_tgt = create_collection(client_tgt, "WineReviewMT", enable_mt=True)
import weaviate, { Collection, WeaviateClient } from '@weaviate/node'

let client_src: WeaviateClient,client_tgt: WeaviateClient;
let reviews_mt_tgt, reviews_mt_src;

client_src = await weaviate.connectToLocal({
})

client_tgt = await weaviate.connectToLocal({
port: 8090,
grpcPort: 50061,
})

async function createCollection(clientIn: WeaviateClient, collectionName: string, enableMt: boolean) {
let reviews = clientIn.collections.create({
name: collectionName,
multiTenancy: {
enabled: enableMt
},
// Additional settings not shown
})

return reviews
}

reviews_mt_tgt = createCollection(client_tgt, "WineReviewMT", true)
  private static CollectionHandle<Map<String, Object>> createCollection(
WeaviateClient clientIn, String collectionName, boolean enableMt)
throws IOException {
clientIn.collections.create(collectionName,
col -> col.multiTenancy(c -> c.enabled(enableMt))
// Additional settings not shown
.vectorConfig(VectorConfig.text2vecTransformers())
.generativeModule(Generative.cohere())
.properties(Property.text("review_body"), Property.text("title"),
Property.text("country"), Property.integer("points"),
Property.number("price")));

return clientIn.collections.use(collectionName);
}

void createTenants() throws IOException {
var reviewsMtTgt = clientTgt.collections.use("WineReviewMT");

var tenantsTgt =
List.of(Tenant.active("tenantA"), Tenant.active("tenantB"));
reviewsMtTgt.tenants.create(tenantsTgt);
}
void createTenantToTenant() throws IOException {
createCollection(clientTgt, "WineReviewMT", true);
}
private static async Task<CollectionClient> CreateCollection(
WeaviateClient clientIn,
string collectionName,
bool enableMt
)
{
return await clientIn.Collections.Create(
new CollectionCreateParams
{
Name = collectionName,
MultiTenancyConfig = new MultiTenancyConfig { Enabled = enableMt },
VectorConfig = Configure.Vector("default", v => v.Text2VecTransformers()),
Properties =
[
Property.Text("review_body"),
Property.Text("title"),
Property.Text("country"),
Property.Int("points"),
Property.Number("price"),
],
}
);
}

private async Task CreateTenants()
{
var reviewsMtTgt = clientTgt.Collections.Use("WineReviewMT");

var tenantsTgt = new[]
{
new Tenant { Name = "tenantA" },
new Tenant { Name = "tenantB" },
};
await reviewsMtTgt.Tenants.Create(tenantsTgt);
}

private async Task CreateTenantToTenant()
{
await CreateCollection(clientTgt, "WineReviewMT", true);
}

Step 2: Create the tenant(s)​

Add tenants at the target instance before adding data objects.

py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
tenants_tgt = [wvc.tenants.Tenant(name="tenantA"), wvc.tenants.Tenant(name="tenantB")]

reviews_mt_tgt = client_tgt.collections.get("WineReviewMT")
reviews_mt_tgt.tenants.create(tenants_tgt)
let tenantsTgt = [
{ name: 'tenantA'},
{ name: 'tenantB'}
]

reviews_mt_tgt = client_tgt.collections.use("WineReviewMT")
reviews_mt_tgt.tenants.create(tenantsTgt)
  void createTenants() throws IOException {
var reviewsMtTgt = clientTgt.collections.use("WineReviewMT");

var tenantsTgt =
List.of(Tenant.active("tenantA"), Tenant.active("tenantB"));
reviewsMtTgt.tenants.create(tenantsTgt);
}
private async Task CreateTenants()
{
var reviewsMtTgt = clientTgt.Collections.Use("WineReviewMT");

var tenantsTgt = new[]
{
new Tenant { Name = "tenantA" },
new Tenant { Name = "tenantB" },
};
await reviewsMtTgt.Tenants.Create(tenantsTgt);
}

Step 3: Migrate the data​

Migrate:

  • The source tenant data from source collection in the client_src instance
  • to target tenant data from target collection in the client_tgt instance
py docs  API docs
More infoCode snippets in the documentation reflect the latest client library and Weaviate Database version. Check the Release notes for specific versions.

If a snippet doesn't work or you have feedback, please open a GitHub issue.
def migrate_data(collection_src: Collection, collection_tgt: Collection):

with collection_tgt.batch.fixed_size(batch_size=100) as batch:
for q in tqdm(collection_src.iterator(include_vector=True)):
batch.add_object(
properties=q.properties,
vector={
"default": q.vector["default"],
},
uuid=q.uuid
)

return True


reviews_mt_src = client_src.collections.get("WineReviewMT")
reviews_src_tenant_a = reviews_mt_src.with_tenant("tenantA")
reviews_mt_tgt = client_tgt.collections.get("WineReviewMT")
reviews_tgt_tenant_a = reviews_mt_tgt.with_tenant(tenants_tgt[0].name)

migrate_data(reviews_src_tenant_a, reviews_tgt_tenant_a)

client_src.close()
client_tgt.close()
import weaviate, { Collection, WeaviateClient } from '@weaviate/node'

let client_src: WeaviateClient,client_tgt: WeaviateClient;
let reviews_mt_tgt, reviews_mt_src;

let maxItems = await reviews_src.length()
let counter: number = 0

async function migrateData(collection_src: Collection, collection_tgt: Collection) {
let itemsToInsert = []
const promises = []

for await (const item of collection_src.iterator({ includeVector: true })) {
// Check if we've reached the maximum items
if (counter >= maxItems) {
console.log(`Reached maximum items limit of ${maxItems}`);
break;
}

counter++;
if (counter % 500 == 0)
console.log(`Import: ${counter}`)

let objectToInsert = {
properties: item.properties,
vectors: item.vectors.default,
uuid: item.uuid,
}

// Add object to batching array
itemsToInsert.push(objectToInsert)

if (itemsToInsert.length == 500 || counter == maxItems) {
try {
const response = await collection_tgt.data.insertMany(itemsToInsert);

if (response.hasErrors) {
throw new Error("Error in batch import!");
}

console.log(`Successfully imported batch of ${itemsToInsert.length} items`);
itemsToInsert = [];
} catch (error) {
console.error('Error importing batch:', error);
}
}
}

}
// Variables initialized above
reviews_mt_src = client_src.collections.use("WineReviewMT")
reviews_src_tenant_a = reviews_mt_src.withTenant("tenantA")
reviews_mt_tgt = client_tgt.collections.use("WineReviewMT")
reviews_tgt_tenant_a = reviews_mt_tgt.withTenant(tenantsTgt[0].name)

migrateData(reviews_src_tenant_a, reviews_tgt_tenant_a)

client_src.close()
client_tgt.close()
  private void migrateData(CollectionHandle<Map<String, Object>> collectionSrc,
CollectionHandle<Map<String, Object>> collectionTgt) {
System.out.println("Starting data migration...");
List<WeaviateObject<Map<String, Object>>> sourceObjects = StreamSupport
.stream(collectionSrc.paginate(p -> p.includeVector()).spliterator(),
false)
.map(readObj -> WeaviateObject
.<Map<String, Object>>of(c -> c.properties(readObj.properties())
.uuid(readObj.uuid())
.vectors(readObj.vectors())))
.collect(Collectors.toList());

collectionTgt.data.insertMany(sourceObjects);

System.out.println("Data migration complete.");
}

void testTenantToTenant() throws IOException {
createTenantToTenant();
createTenants();

var reviewsMtSrc = clientSrc.collections.use("WineReviewMT");
var reviewsMtTgt = clientTgt.collections.use("WineReviewMT");
var reviewsSrcTenantA = reviewsMtSrc.withTenant("tenantA");
var reviewsTgtTenantA = reviewsMtTgt.withTenant("tenantA");

migrateData(reviewsSrcTenantA, reviewsTgtTenantA);

}
private async Task MigrateData<T>(
CollectionClient collectionSrc,
CollectionClient collectionTgt
)
{
Console.WriteLine("Starting data migration...");

// Fetch source objects
var response = await collectionSrc.Query.FetchObjects(limit: 10000, includeVectors: true);

// Map to Strong Type List
var sourceObjects = new List<T>();
foreach (var obj in response.Objects)
{
// Deserialize the inner properties Dictionary to the POCO type
var json = JsonSerializer.Serialize(obj.Properties);
var typedObj = JsonSerializer.Deserialize<T>(json);
if (typedObj != null)
{
sourceObjects.Add(typedObj);
}
}

// InsertMany using Strong Types
await collectionTgt.Data.InsertMany(sourceObjects.ToArray());

Console.WriteLine($"Data migration complete. Migrated {sourceObjects.Count} objects.");
}

public async Task TestTenantToTenant()
{
await CreateTenantToTenant();
await CreateTenants();

var reviewsMtSrc = clientSrc.Collections.Use("WineReviewMT");
var reviewsMtTgt = clientTgt.Collections.Use("WineReviewMT");
var reviewsSrcTenantA = reviewsMtSrc.WithTenant("tenantA");
var reviewsTgtTenantA = reviewsMtTgt.WithTenant("tenantA");

await MigrateData<WineReviewModel>(reviewsSrcTenantA, reviewsTgtTenantA);
}

Questions and feedback​