Multi-tenancy operations
Multi-tenancy provides data isolation. Each tenant is stored on a separate shard. Data stored in one tenant is not visible to another tenant. If your application serves many different users, multi-tenancy keeps their data private and makes database operations more efficient.
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 multi-tenancy, set multiTenancyConfig
in the collection definition:
- Python Client v4
- Python Client v3
- JS/TS Client v3
- JS/TS Client v2
- 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(enabled=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)
Automatically add new tenants
Weavite can create new tenants automatically. By default, Weaviate returns an error if you try to insert an object into a non-existent tenant. To create a new tenant instead, set autoTenantCreation
to true
in the collection definition.
Set autoTenantCreation
when you create the collection, or update the setting as needed.
Automatic tenant creation is very useful when you import a large number of objects. Be cautious if your data is likely to have small inconsistencies or typos. For example, the names TenantOne
, tenantOne
, and TenntOne
will create three different tenants.
Create a collection
- Python (v4)
- cURL
from weaviate.classes.config import Configure
multi_collection = client.collections.create(
name="CollectionWithAutoMTEnabled",
# Enable automatic tenant creation
multi_tenancy_config=Configure.multi_tenancy(
enabled=True,
auto_tenant_creation=True
)
)
curl localhost:8080/v1/schema -H 'content-type:application/json' -d \
'{
"class": "Customer",
"properties": [
{
"name": "customer_name",
"dataType": ["text"]
},
{
"name": "customer_category",
"dataType": ["text"]
}
],
"multiTenancyConfig": {
"enabled": true,
"autoTenantCreation": true
}
}'
Update a collection
Use the client to update the auto-tenant creation setting.
- Python (v4)
from weaviate.collections.classes.config import Reconfigure
collection = client.collections.get(collection_name)
collection.config.update(
multi_tenancy_config=Reconfigure.multi_tenancy(auto_tenant_creation=True)
)
Add new tenants manually
To add tenants to a collection, specify the collection and the new tenants. Optionally, specify the tenant activity status as HOT
(active, default) or COLD
(inactive).
This example adds tenantA
to the MultiTenancyCollection
collection:
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 Client v4
- Python Client v3
- JS/TS Client v3
- JS/TS Client v2
- 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 all tenants
List existing tenants in a collection.
This example lists the tenants in the MultiTenancyCollection
collection:
- Python Client v4
- Python Client v3
- JS/TS Client v3
- JS/TS Client v2
- 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)
Get tenants by name
Get tenants from a collection by name. Note that non-existent tenant names are ignored in the response.
This example returns tenantA
and tenantB
from the MultiTenancyCollection
collection:
- Python (v4)
- JS/TS v3
multi_collection = client.collections.get("MultiTenancyCollection")
tenant_names = ["tenantA", "tenantB", "nonExistentTenant"] # `nonExistentTenant`` does not exist and will be ignored
tenants_response = multi_collection.tenants.get_by_names(tenant_names)
for k, v in tenants_response.items():
print(k, v)
// Coming soon
Get one tenant
Get a particular tenant from a collection.
This example returns a tenant from the MultiTenancyCollection
collection:
- Python (v4)
- JS/TS v3
multi_collection = client.collections.get("MultiTenancyCollection")
tenant_obj = multi_collection.tenants.get_by_name(tenant_name)
print(tenant_obj.name)
// Coming soon
Delete tenants
To delete tenants from a collection, specify the collection and the tenants. The delete operation ignores tenant names if the named tenant is not a part of the collection.
In this example, Weaviate removes tenantB
and tenantX
from the MultiTenancyCollection
collection.
- Python Client v4
- Python Client v3
- JS/TS Client v3
- JS/TS Client v2
- 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 Client 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 Client v4
- Python Client v3
- JS/TS Client v3
- JS/TS Client v2
- 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 Client v4
- Python Client v3
- JS/TS Client v3
- JS/TS Client v2
- 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 Client v4
- Python Client v3
- JS/TS Client v3
- JS/TS Client v2
- 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 the user forum.