Multi-tenancy operations
Multi-tenancy isolates data between tenants (typically end users) in a Weaviate instance, for example in a SaaS application. Each tenant is a separate shard in Weaviate.
Multi-tenancy availability
- Multi-tenancy added in
v1.20
- (Experimental) Tenant activity status setting added in
v1.21
Enable multi-tenancy
Multi-tenancy is disabled by default. To enable it, set the multiTenancyConfig
variable in the collection definition as shown below:
- Python (v4)
- Python (v3)
- JS/TS (Beta)
- JS/TS
- Java
- Go
from weaviate.classes.config import Configure
multi_collection = client.collections.create(
name="MultiTenancyCollection",
# Enable multi-tenancy on the new collection
multi_tenancy_config=Configure.multi_tenancy(True)
)
client.schema.create_class({
"class": "MultiTenancyCollection",
"multiTenancyConfig": {"enabled": True}
})
const result = await client.collections.create({
name: 'MultiTenancyCollection',
multiTenancy: weaviate.configure.multiTenancy({enabled: true})
}
)
await client.schema
.classCreator().withClass({
class: 'MultiTenancyCollection',
multiTenancyConfig: { enabled: true },
})
.do();
WeaviateClass multiTenancyCollection = WeaviateClass.builder()
.className("MultiTenancyCollection")
.multiTenancyConfig(MultiTenancyConfig.builder().enabled(true).build())
.build();
client.schema().classCreator()
.withClass(multiTenancyCollection)
.run();
client.Schema().ClassCreator().
WithClass(&models.Class{
Class: "MultiTenancyCollection",
MultiTenancyConfig: &models.MultiTenancyConfig{
Enabled: true,
},
}).
Do(ctx)
Add tenant(s)
Add tenants to a collection (MultiTenancyCollection
) with a name (e.g. tenantA
) and an optional tenant activity status as HOT
(active, default) or COLD
(inactive).
Additional information
Tenant status is available from Weaviate 1.21
onwards.
A tenant name can only contain alphanumeric characters (a-z, A-Z, 0-9), underscore (_), and hyphen (-), with a length of 4 to 64 characters.
- Python (v4)
- Python (v3)
- JS/TS (Beta)
- JS/TS
- Java
- Go
from weaviate.classes.tenants import Tenant
# Add two tenants to the collection
multi_collection.tenants.create(
tenants=[
Tenant(name="tenantA"),
Tenant(name="tenantB"),
]
)
from weaviate import Tenant
client.schema.add_class_tenants(
class_name="MultiTenancyCollection", # The class to which the tenants will be added
tenants=[Tenant(name="tenantA"), Tenant(name="tenantB")]
)
const multiCollection = client.collections.get('MultiTenancyCollection');
await multiCollection.tenants.create([
{ name: 'tenantA'},
{ name: 'tenantB'}
])
let tenants = await client.schema
.tenantsCreator(
'MultiTenancyCollection',
[{ name: 'tenantA' }, { name: 'tenantB' }]
)
.do();
client.schema().tenantsCreator()
.withClassName("MultiTenancyCollection")
.withTenants(
Tenant.builder().name("tenantA").build(),
Tenant.builder().name("tenantB").build()
)
.run();
client.Schema().TenantsCreator().
WithClassName("MultiTenancyCollection").
WithTenants(models.Tenant{Name: "tenantA"}, models.Tenant{Name: "tenantB"}).
Do(ctx)
List tenant(s)
List existing tenants in a collection (e.g.MultiTenancyCollection
):
- Python (v4)
- Python (v3)
- JS/TS (Beta)
- JS/TS
- Java
- Go
multi_collection = client.collections.get("MultiTenancyCollection")
tenants = multi_collection.tenants.get()
print(tenants)
tenants = client.schema.get_class_tenants(
class_name="MultiTenancyCollection" # The class from which the tenants will be retrieved
)
const multiCollection = client.collections.get('MultiTenancyCollection');
const tenants = await multiCollection.tenants.get()
console.log(tenants)
tenants = await client.schema
.tenantsGetter('MultiTenancyCollection')
.do();
client.schema().tenantsGetter()
.withClassName("MultiTenancyCollection")
.run();
tenants, err := client.Schema().TenantsGetter().
WithClassName("MultiTenancyCollection").
Do(ctx)
Delete tenant(s)
Delete one or more existing tenants in a collection (e.g. MultiTenancyCollection
) and tenant names (e.g. ["tenantB", "tenantX"]
).
Non-existing tenants are ignored.
- Python (v4)
- Python (v3)
- JS/TS (Beta)
- JS/TS
- Java
- Go
multi_collection = client.collections.get("MultiTenancyCollection")
# Remove a list of tenants - tenantX will be ignored.
multi_collection.tenants.remove(["tenantB", "tenantX"])
client.schema.remove_class_tenants(
class_name="MultiTenancyCollection", # The class from which the tenants will be removed
tenants=["tenantB", "tenantX"] # The tenants to be removed. tenantX will be ignored.
)
const multiCollection = client.collections.get('MultiTenancyCollection');
await multiCollection.tenants.remove([
{ name: 'tenantB'},
{ name: 'tenantX'} // tenantX will be ignored
])
await client.schema
.tenantsDeleter('MultiTenancyCollection', ['tenantB', 'tenantX']) // tenantX will be ignored
.do();
client.schema().tenantsDeleter()
.withClassName("MultiTenancyCollection")
.withTenants("tenantB", "tenantX") // tenantX will be ignored
.run();
client.Schema().TenantsDeleter().
WithClassName("MultiTenancyCollection").
WithTenants("tenantB", "tenantX"). // tenantX will be ignored
Do(ctx)
Update tenant activity status
Update existing tenants' activity status to active (HOT
) or inactive (COLD
).
- Python (v4)
from weaviate.classes.tenants import Tenant
multi_collection = client.collections.get("MultiTenancyCollection")
multi_collection.tenants.update(tenants=[
Tenant(
name="tenantA",
activity_status=weaviate.schema.TenantActivityStatus.COLD
)
])
Additional information
- This feature was added in
v1.21
- Other client code examples coming soon
- For now, please send a PUT request through the REST API endpoint to update the tenant activity status.
CRUD operations
Multi-tenancy collections require tenant name (e.g. tenantA
) with each CRUD operation, as shown in the object creation example below.
- Python (v4)
- Python (v3)
- JS/TS (Beta)
- JS/TS
- Java
- Go
multi_collection = client.collections.get("MultiTenancyCollection")
# Get collection specific to the required tenant
multi_tenantA = multi_collection.with_tenant("tenantA")
# Insert an object to tenantA
object_id = multi_tenantA.data.insert(
properties={
"question": "This vector DB is OSS & supports automatic property type inference on import"
}
)
object_id = client.data_object.create(
class_name="MultiTenancyCollection", # The class to which the object will be added
data_object={
"question": "This vector DB is OSS & supports automatic property type inference on import"
},
tenant="tenantA" # The tenant to which the object will be added
)
const multiCollection = client.collections.get('MultiTenancyCollection');
const multiTenantA = multiCollection.withTenant('tenantA')
await multiTenantA.data.insert({
question: 'This vector DB is OSS & supports automatic property type inference on import'
})
let object = await client.data.creator()
.withClassName('MultiTenancyCollection') // The class to which the object will be added
.withProperties({
question: 'This vector DB is OSS & supports automatic property type inference on import',
})
.withTenant('tenantA') // The tenant to which the object will be added
.do();
Result<WeaviateObject> result = client.data().creator()
.withClassName("MultiTenancyCollection") // The class to which the object will be added
.withProperties(new HashMap<String, Object>() {{
put("question", "This vector DB is OSS & supports automatic property type inference on import");
}})
.withTenant("tenantA") // The tenant to which the object will be added
.run();
object, err := client.Data().Creator().
WithClassName("MultiTenancyCollection"). // The class to which the object will be added
WithProperties(map[string]interface{}{
"question": "This vector DB is OSS & supports automatic property type inference on import",
}).
WithTenant("tenantA"). // The tenant to which the object will be added
Do(ctx)
Search queries
Multi-tenancy collections require the tenant name (e.g. tenantA
) with each Get
and Aggregate
query operation.
- Python (v4)
- Python (v3)
- JS/TS (Beta)
- JS/TS
- Java
- Go
multi_collection = client.collections.get("MultiTenancyCollection")
# Get collection specific to the required tenant
multi_tenantA = multi_collection.with_tenant("tenantA")
# Query tenantA
result = multi_tenantA.query.fetch_objects(
limit=2,
)
print(result.objects[0].properties)
result = (
client.query.get("MultiTenancyCollection", ["question"])
.with_tenant("tenantA")
.do()
)
const multiCollection = await client.collections.get('MultiTenancyCollection');
const multiTenantA = multiCollection.withTenant('tenantA')
const objectA = await multiTenantA.query.fetchObjects({
limit: 2
})
console.log(objectA.objects)
const result = await client.graphql
.get()
.withClassName('MultiTenancyCollection')
.withFields('question')
.withTenant('tenantA')
.do();
Result<GraphQLResponse> result = client.graphQL().get()
.withClassName("MultiTenancyCollection")
.withFields(Field.builder().name("question").build())
.withTenant("tenantA")
.run();
result, err := client.GraphQL().Get().
WithClassName("MultiTenancyCollection").
WithFields(graphql.Field{Name: "question"}).
WithTenant("tenantA").
Do(ctx)
Cross-references
A cross-reference can be added from a multi-tenancy collection object to:
- A non-multi-tenancy collection object, or
- An object belonging to the same tenant.
Multi-tenancy collections require the tenant name (e.g. tenantA
) when creating, updating or deleting cross-references.
- Python (v4)
- Python (v3)
- JS/TS (Beta)
- JS/TS
- Java
- Go
from weaviate.classes.config import ReferenceProperty
multi_collection = client.collections.get("MultiTenancyCollection")
# Add the cross-reference property to the multi-tenancy class
multi_collection.config.add_reference(
ReferenceProperty(
name="hasCategory",
target_collection="JeopardyCategory"
)
)
# Get collection specific to the required tenant
multi_tenantA = multi_collection.with_tenant(tenant="tenantA")
# Add reference from MultiTenancyCollection object to a JeopardyCategory object
multi_tenantA.data.reference_add(
from_uuid=object_id, # MultiTenancyCollection object id (a Jeopardy question)
from_property="hasCategory",
to=category_id # JeopardyCategory id
)
# Add the cross-reference property to the multi-tenancy class
client.schema.property.create("MultiTenancyCollection", {
"name": "hasCategory",
"dataType": ["JeopardyCategory"],
})
client.data_object.reference.add(
from_uuid=object_id, # MultiTenancyCollection object id (a Jeopardy question)
from_class_name="MultiTenancyCollection",
from_property_name="hasCategory",
tenant="tenantA",
to_class_name="JeopardyCategory",
to_uuid=category_id
)
// Add the cross-reference property to the multi-tenancy class
const multiCollection = await client.collections.get('MultiTenancyCollection');
const categoryId = '...'
const objectId = '...'
await multiCollection.config.addReference({
name: 'hasCategory',
targetCollection: 'JeopardyCategory'
})
const multiTenantA = multiCollection.withTenant('tenantA')
await multiTenantA.data.referenceAdd({
fromUuid: objectId,
fromProperty: 'hasCategory',
to: categoryId
})
// Add the cross-reference property to the multi-tenancy class
await client.schema.propertyCreator()
.withClassName('MultiTenancyCollection')
.withProperty({
'name': 'hasCategory',
'dataType': ['JeopardyCategory'],
})
.do();
// Create the cross-reference from MultiTenancyCollection object to the JeopardyCategory object
await client.data
.referenceCreator()
.withClassName('MultiTenancyCollection')
.withTenant('tenantA')
.withId(object.id) // MultiTenancyCollection object id (a Jeopardy question)
.withReferenceProperty('hasCategory')
.withReference(
client.data
.referencePayloadBuilder()
.withClassName('JeopardyCategory')
.withId(category.id)
.payload()
)
.do();
// Add the cross-reference property to the multi-tenancy class
client.schema().propertyCreator()
.withClassName("MultiTenancyCollection")
.withProperty(Property.builder()
.name("hasCategory")
.dataType(Collections.singletonList("JeopardyCategory")).build()
)
.run();
// Create the cross-reference from MultiTenancyCollection object to the JeopardyCategory object
client.data().referenceCreator()
.withClassName("MultiTenancyCollection")
.withTenant("tenantA")
.withID(object.getId()) // MultiTenancyCollection object id (a Jeopardy question)
.withReferenceProperty("hasCategory")
.withReference(
client.data()
.referencePayloadBuilder()
.withClassName("JeopardyCategory")
.withID(category.getId())
.payload()
)
.run();
// Add the cross-reference property to the multi-tenancy class
client.Schema().PropertyCreator().
WithClassName("MultiTenancyCollection").
WithProperty(&models.Property{
Name: "hasCategory",
DataType: []string{"JeopardyCategory"},
}).
Do(ctx)
// Create the cross-reference from MultiTenancyCollection object to the JeopardyCategory object
client.Data().ReferenceCreator().
WithClassName("MultiTenancyCollection").
WithTenant("tenantA").
WithID(object.ID.String()). // MultiTenancyCollection object id (a Jeopardy question)
WithReferenceProperty("hasCategory").
WithReference(client.Data().ReferencePayloadBuilder().
WithClassName("JeopardyCategory").
WithID(category.ID.String()).
Payload()).
Do(ctx)
Related pages
- Connect to Weaviate
- How to: Configure a schema
- References: REST API: Schema
- Concepts: Data Structure: Multi-tenancy
Questions and feedback
If you have any questions or feedback, let us know in our user forum.