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.
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 collectiondata in theclient_srcinstance - to
target collectionin theclient_tgtinstance
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.
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.
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 collectiondata in theclient_srcinstance - to
target tenantdata fromtarget collectionin theclient_tgtinstance
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.
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 tenantdata fromsource collectionin theclient_srcinstance - to
target collectionin theclient_tgtinstance
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.
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.
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 tenantdata fromsource collectionin theclient_srcinstance - to
target tenantdata fromtarget collectionin theclient_tgtinstance
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);
}
Related pages
Questions and feedback
Have a question or feedback? Here's how to reach us.
