Cross-references
Queries involving cross-references can be slower than queries that do not involve cross-references, especially at scale such as for multiple objects or complex queries.
At the first instance, we strongly encourage you to consider whether you can avoid using cross-references in your data schema. As a scalable AI database, Weaviate is well-placed to perform complex queries with vector, keyword and hybrid searches involving filters. You may benefit from rethinking your data schema to avoid cross-references where possible.
For example, instead of creating separate "Author" and "Book" collections with cross-references, consider embedding author information directly in Book objects and using searches and filters to find books by author characteristics.
Use cross-references to establish directional relationships between collections.
A query never returns cross-referenced data unless you ask for it. Request it explicitly with return_references, returnReferences, or similar. If your results have no references in them, this is usually why. See Read cross-references below.
Additional information
Notes:
- Cross-references does not affect object vectors of the source or the target objects.
- For multi-tenancy collection, you can establish a cross-reference from a multi-tenancy collection object to:
- A non-multi-tenancy collection object, or
- A multi-tenancy collection object belonging to the same tenant.
Define a cross-reference property
Include the reference property in the collection definition before adding cross-references to it.
If a snippet doesn't work or you have feedback, please open a GitHub issue.
from weaviate.classes.config import Property, DataType, ReferenceProperty
client.collections.create(
name="JeopardyQuestion",
description="A Jeopardy! question",
properties=[
Property(name="question", data_type=DataType.TEXT),
Property(name="answer", data_type=DataType.TEXT),
],
references=[
ReferenceProperty(
name="hasCategory",
target_collection="JeopardyCategory"
)
]
)
await client.collections.create({
name: 'JeopardyQuestion',
properties: [
{ name: 'question' , dataType: 'text' },
{ name: 'answer', dataType: 'text' }
],
references: [{
name: 'hasCategory',
targetCollection: 'JeopardyCategory',
}]
})
client.collections.create("JeopardyCategory",
col -> col.description("A Jeopardy! category")
.properties(Property.text("title")));
client.collections.create("JeopardyQuestion",
col -> col.description("A Jeopardy! question")
.properties(Property.text("question"), Property.text("answer"))
.references(ReferenceProperty.to("hasCategory", "JeopardyCategory"))
);
await client.Collections.Create(
new CollectionCreateParams
{
Name = "JeopardyCategory",
Description = "A Jeopardy! category",
Properties = [Property.Text("title")],
}
);
await client.Collections.Create(
new CollectionCreateParams
{
Name = "JeopardyQuestion",
Description = "A Jeopardy! question",
Properties = [Property.Text("question"), Property.Text("answer")],
References = [new Reference("hasCategory", "JeopardyCategory")],
}
);
Add a cross-reference property
It is also possible to add a cross-reference property to an existing collection definition.
If a snippet doesn't work or you have feedback, please open a GitHub issue.
from weaviate.classes.config import ReferenceProperty
# Add the reference to JeopardyQuestion, after it was created
category = client.collections.use("JeopardyCategory")
# category.config.add_reference(
category.config.add_reference(
ReferenceProperty(
name="hasQuestion",
target_collection="JeopardyQuestion"
)
)
// Add the "hasQuestion" cross-reference property to the JeopardyCategory collection
const category = client.collections.use('JeopardyCategory')
await category.config.addReference({
name: 'hasQuestion',
targetCollection: 'JeopardyQuestion'
})
// Add the reference to JeopardyQuestion, after it was created
category := client.Collections.Use("JeopardyCategory")
err := category.Config.AddReference(ctx, collections.Reference{
Name: "hasQuestion",
Collections: []string{"JeopardyQuestion"},
})
if err != nil {
// handle error
panic(err)
}
var category = client.collections.use("JeopardyCategory");
category.config.addReference(
"hasQuestion", "JeopardyQuestion"
);
var category = client.Collections.Use("JeopardyCategory");
await category.Config.AddReference(
Property.Reference("hasQuestion", "JeopardyQuestion")
);
Create an object with a cross-reference
Specify a cross-reference when creating an object.
If a snippet doesn't work or you have feedback, please open a GitHub issue.
questions = client.collections.use("JeopardyQuestion")
questions.data.insert(
properties=properties, # A dictionary with the properties of the object
uuid=obj_uuid, # The UUID of the object
references={"hasCategory": category_uuid}, # e.g. {"hasCategory": "583876f3-e293-5b5b-9839-03f455f14575"}
)
const category = client.collections.use('JeopardyCategory')
const dataObject = {'name': 'Science'}
const response = await category.data.insert({
properties: dataObject,
references: {
'hasCategory': categoryId // e.g. {'hasCategory': '583876f3-e293-5b5b-9839-03f455f14575'}
}
})
console.log('UUID: ', response)
var questions = client.collections.use("JeopardyQuestion");
var result = questions.data.insert(properties, // A map with the properties of the object
opt -> opt
.reference("hasCategory", ObjectReference.uuids(categoryUuid)) // e.g. {"hasCategory":
// "583876f3-e293-5b5b-9839-03f455f14575"}
);
var questions = client.Collections.Use("JeopardyQuestion");
var newObject = await questions.Data.Insert(
properties, // The properties of the object
references: [new ObjectReference("hasCategory", categoryUuid)]
);
Add a one-way cross-reference
Specify the required id and properties for the source and the target.
If a snippet doesn't work or you have feedback, please open a GitHub issue.
questions = client.collections.use("JeopardyQuestion")
questions.data.reference_add(
from_uuid=question_obj_id,
from_property="hasCategory",
to=category_obj_id
)
const jeopardy = client.collections.use('JeopardyCategory')
await jeopardy.data.referenceAdd({
fromProperty: 'hasCategory',
fromUuid: questionObjectId,
to: categoryObjectId,
})
sfID := "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
usCitiesID := "20ffc68d-986b-5e71-a680-228dba18d7ef"
client.Data().ReferenceCreator().
WithClassName("JeopardyQuestion").
WithID(sfID).
WithReferenceProperty("hasCategory").
WithReference(client.Data().ReferencePayloadBuilder().
WithClassName("JeopardyCategory").
WithID(usCitiesID).
Payload()).
Do(ctx)
questionID := uuid.MustParse("d2e3f4a5-b6c7-4d8e-8f9a-9b0c1d2e3f4a") // The source object.
categoryID := uuid.MustParse("c2d3e4f5-a6b7-4c8d-8e9f-8a9b0c1d2e3f") // The target object.
questions := client.Collections.Use("JeopardyQuestion")
_, err := questions.Data.AddReferences(ctx, data.Reference{
Origin: data.ObjectPath{
Collection: "JeopardyQuestion",
Property: "hasCategory",
UUID: questionID,
},
UUID: categoryID,
})
if err != nil {
// handle error
panic(err)
}
questions.data.referenceAdd(questionObjId, "hasCategory",
ObjectReference.uuids(categoryObjId)[0]
);
await questions.Data.ReferenceAdd(
from: questionObjId,
fromProperty: "hasCategory",
to: categoryObjId
);
Add two-way cross-references
This requires adding reference properties in both directions, and adding two cross-references per object pair (from A -> to B and from B -> to A).
Create the JeopardyCategory collection:
If a snippet doesn't work or you have feedback, please open a GitHub issue.
from weaviate.classes.config import Property, DataType, ReferenceProperty
category = client.collections.create(
name="JeopardyCategory",
description="A Jeopardy! category",
properties=[
Property(name="title", data_type=DataType.TEXT)
]
)
const category = client.collections.create({
name: "JeopardyCategory",
description: "A Jeopardy! category",
properties: [
{ name: "title", dataType: "text" }
]
})
client.collections.create("JeopardyCategory",
col -> col.description("A Jeopardy! category")
.properties(Property.text("title")));
await client.Collections.Create(
new CollectionCreateParams
{
Name = "JeopardyCategory",
Description = "A Jeopardy! category",
Properties = [Property.Text("title")],
}
);
Create the JeopardyQuestion collection including the reference property to JeopardyCategory:
If a snippet doesn't work or you have feedback, please open a GitHub issue.
client.collections.create(
name="JeopardyQuestion",
description="A Jeopardy! question",
properties=[
Property(name="question", data_type=DataType.TEXT),
Property(name="answer", data_type=DataType.TEXT),
],
references=[
ReferenceProperty(
name="hasCategory",
target_collection="JeopardyCategory"
)
]
)
const jeopardyQuestionCollection = client.collections.create({
name: 'JeopardyQuestion',
properties: [
{ name: 'question' , dataType: 'text' },
{ name: 'answer', dataType: 'text' }
],
references: [{
name: 'hasCategory',
targetCollection: 'JeopardyCategory'
}]
})
client.collections.create("JeopardyQuestion",
col -> col.description("A Jeopardy! question")
.properties(Property.text("question"), Property.text("answer"))
.references(ReferenceProperty.to("hasCategory", "JeopardyCategory"))
);
await client.Collections.Create(
new CollectionCreateParams
{
Name = "JeopardyQuestion",
Description = "A Jeopardy! question",
Properties = [Property.Text("question"), Property.Text("answer")],
References = [new Reference("hasCategory", "JeopardyCategory")],
}
);
Modify JeopardyCategory to add the reference to JeopardyQuestion:
If a snippet doesn't work or you have feedback, please open a GitHub issue.
from weaviate.classes.config import ReferenceProperty
# Add the reference to JeopardyQuestion, after it was created
category = client.collections.use("JeopardyCategory")
# category.config.add_reference(
category.config.add_reference(
ReferenceProperty(
name="hasQuestion",
target_collection="JeopardyQuestion"
)
)
// Add the "hasQuestion" cross-reference property to the JeopardyCategory collection
const category = client.collections.use('JeopardyCategory')
await category.config.addReference({
name: 'hasQuestion',
targetCollection: 'JeopardyQuestion'
})
// Add the reference to JeopardyQuestion, after it was created
category := client.Collections.Use("JeopardyCategory")
err := category.Config.AddReference(ctx, collections.Reference{
Name: "hasQuestion",
Collections: []string{"JeopardyQuestion"},
})
if err != nil {
// handle error
panic(err)
}
var category = client.collections.use("JeopardyCategory");
category.config.addReference(
"hasQuestion", "JeopardyQuestion"
);
var category = client.Collections.Use("JeopardyCategory");
await category.Config.AddReference(
Property.Reference("hasQuestion", "JeopardyQuestion")
);
And add the cross-references:
If a snippet doesn't work or you have feedback, please open a GitHub issue.
# For the "San Francisco" JeopardyQuestion object, add a cross-reference to the "U.S. CITIES" JeopardyCategory object
questions = client.collections.use("JeopardyQuestion")
questions.data.reference_add(
from_uuid=question_obj_id,
from_property="hasCategory",
to=category_obj_id
)
# For the "U.S. CITIES" JeopardyCategory object, add a cross-reference to "San Francisco"
categories = client.collections.use("JeopardyCategory")
categories.data.reference_add(
from_uuid=category_obj_id,
from_property="hasQuestion",
to=question_obj_id
)
// For the "San Francisco" JeopardyQuestion object, add a cross-reference to the "U.S. CITIES" JeopardyCategory object
const questions = client.collections.use("JeopardyQuestion")
await questions.data.referenceAdd({
fromUuid: questionObjectId,
fromProperty: 'hasCategory',
to: catogoryObjectId
})
// For the "U.S. CITIES" JeopardyCategory object, add a cross-reference to "San Francisco"
const category = client.collections.use("JeopardyCategory")
await category.data.referenceAdd({
fromUuid: catogoryObjectId,
fromProperty: 'hasQuestion',
to: questionObjectId
})
sfID := "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
usCitiesID := "20ffc68d-986b-5e71-a680-228dba18d7ef"
// First, add the "hasQuestion" cross-reference property to the JeopardyCategory class
client.Schema().PropertyCreator().
WithClassName("JeopardyCategory").
WithProperty(&models.Property{
Name: "hasQuestion",
DataType: []string{"JeopardyQuestion"},
}).
Do(ctx)
// For the "San Francisco" JeopardyQuestion object, add a cross-reference to the "U.S. CITIES" JeopardyCategory object
client.Data().ReferenceCreator().
WithClassName("JeopardyQuestion").
WithID(sfID).
WithReferenceProperty("hasCategory").
WithReference(client.Data().ReferencePayloadBuilder().
WithClassName("JeopardyCategory").
WithID(usCitiesID).
Payload()).
Do(ctx)
// For the "U.S. CITIES" JeopardyCategory object, add a cross-reference to "San Francisco"
client.Data().ReferenceCreator().
WithClassName("JeopardyCategory").
WithID(usCitiesID).
WithReferenceProperty("hasQuestion").
WithReference(client.Data().ReferencePayloadBuilder().
WithClassName("JeopardyQuestion").
WithID(sfID).
Payload()).
Do(ctx)
questionID := uuid.MustParse("a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d") // The "San Francisco" question.
categoryID := uuid.MustParse("b1c2d3e4-f5a6-4b7c-8d9e-1f2a3b4c5d6e") // The "U.S. CITIES" category.
// For the question, add a cross-reference to the category
questions := client.Collections.Use("JeopardyQuestion")
if _, err := questions.Data.AddReferences(ctx, data.Reference{
Origin: data.ObjectPath{Collection: "JeopardyQuestion", Property: "hasCategory", UUID: questionID},
UUID: categoryID,
}); err != nil {
// handle error
panic(err)
}
// For the category, add a cross-reference to the question
categories := client.Collections.Use("JeopardyCategory")
if _, err := categories.Data.AddReferences(ctx, data.Reference{
Origin: data.ObjectPath{Collection: "JeopardyCategory", Property: "hasQuestion", UUID: categoryID},
UUID: questionID,
}); err != nil {
// handle error
panic(err)
}
// For the "San Francisco" JeopardyQuestion object, add a cross-reference to the
// "U.S. CITIES" JeopardyCategory object
questions.data.referenceAdd(questionObjId, "hasCategory",
ObjectReference.uuids(categoryObjId)[0]);
// For the "U.S. CITIES" JeopardyCategory object, add a cross-reference to "San
// Francisco"
categories.data.referenceAdd(categoryObjId, "hasQuestion",
ObjectReference.uuids(questionObjId)[0]);
// For the "San Francisco" JeopardyQuestion object, add a cross-reference to the "U.S. CITIES" JeopardyCategory object
await questions.Data.ReferenceAdd(
from: questionObjId,
fromProperty: "hasCategory",
to: categoryObjId
);
// For the "U.S. CITIES" JeopardyCategory object, add a cross-reference to "San Francisco"
await categories.Data.ReferenceAdd(
from: categoryObjId,
fromProperty: "hasQuestion",
to: questionObjId
);
Add multiple (one-to-many) cross-references
Weaviate allows creation of multiple cross-references from one source object.
If a snippet doesn't work or you have feedback, please open a GitHub issue.
from weaviate.classes.data import DataReference
questions = client.collections.use("JeopardyQuestion")
refs_list = []
for temp_uuid in [category_obj_id, category_obj_id_alt]:
ref_obj = DataReference(
from_uuid=question_obj_id,
from_property="hasCategory",
to_uuid=temp_uuid
)
refs_list.append(ref_obj)
questions.data.reference_add_many(refs_list)
const questions = client.collections.use("JeopardyQuestion")
await questions.data.referenceAddMany(
[{
fromUuid: questionObjectId,
fromProperty: 'hasCategory',
to: catogoryObjectId1
},{
fromUuid: questionObjectId,
fromProperty: 'hasCategory',
to: catogoryObjectId2
}]
)
sfID := "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
usCitiesID := "20ffc68d-986b-5e71-a680-228dba18d7ef"
museumsID := "fec50326-dfa1-53c9-90e8-63d0240bd933"
// Add to "San Francisco" the "U.S. CITIES" category
client.Data().ReferenceCreator().
WithClassName("JeopardyQuestion").
WithID(sfID).
WithReferenceProperty("hasCategory").
WithReference(client.Data().ReferencePayloadBuilder().
WithClassName("JeopardyCategory").
WithID(usCitiesID).
Payload()).
Do(ctx)
// Add the "MUSEUMS" category as well
client.Data().ReferenceCreator().
WithClassName("JeopardyQuestion").
WithID(sfID).
WithReferenceProperty("hasCategory").
WithReference(client.Data().ReferencePayloadBuilder().
WithClassName("JeopardyCategory").
WithID(museumsID).
Payload()).
Do(ctx)
questionID := uuid.MustParse("d1e2f3a4-b5c6-4d7e-8f90-1a2b3c4d5e6f") // The source object.
usCitiesID := uuid.MustParse("e1f2a3b4-c5d6-4e7f-8a90-1b2c3d4e5f60") // A target object.
museumsID := uuid.MustParse("f1a2b3c4-d5e6-4f70-8a91-2b3c4d5e6f70") // Another target object.
questions := client.Collections.Use("JeopardyQuestion")
_, err := questions.Data.AddReferences(ctx,
data.Reference{
Origin: data.ObjectPath{Collection: "JeopardyQuestion", Property: "hasCategory", UUID: questionID},
UUID: usCitiesID,
},
data.Reference{
Origin: data.ObjectPath{Collection: "JeopardyQuestion", Property: "hasCategory", UUID: questionID},
UUID: museumsID,
},
)
if err != nil {
// handle error
panic(err)
}
// Add multiple references - need to add them individually
for (String tempUuid : List.of(categoryObjId, categoryObjIdAlt)) {
questions.data.referenceAdd(questionObjId, "hasCategory",
ObjectReference.uuids(tempUuid)[0]);
}
// Add multiple references - need to add them individually
foreach (var tempUuid in new[] { categoryObjId, categoryObjIdAlt })
{
await questions.Data.ReferenceAdd(
from: questionObjId,
fromProperty: "hasCategory",
to: tempUuid
);
}
Read cross-references
Cross-references can be read as part of the object.
If a snippet doesn't work or you have feedback, please open a GitHub issue.
from weaviate.classes.query import QueryReference
questions = client.collections.use("JeopardyQuestion")
# Include the cross-references in a query response
response = questions.query.fetch_objects( # Or `hybrid`, `near_text`, etc.
limit=2,
return_references=QueryReference(
link_on="hasCategory",
return_properties=["title"]
)
)
# Or include cross-references in a single-object retrieval
obj = questions.query.fetch_object_by_id(
uuid=question_obj_id,
return_references=QueryReference(
link_on="hasCategory",
return_properties=["title"]
)
)
const questions = client.collections.use("JeopardyQuestion")
const response = await questions.query.fetchObjects({ // Or `hybrid`, `nearText`, etc.
limit: 2,
returnReferences: [{
linkOn: 'hasCategory',
returnProperties: ['title']
}]
})
response.objects.forEach(item =>
console.log(JSON.stringify(item.references, null, 2))
)
// Include the cross-references in a query response
var response = questions.query.fetchObjects( // Or `hybrid`, `nearText`, etc.
opt -> opt.limit(2)
.returnReferences(QueryReference.single("hasCategory",
ref -> ref.returnProperties("title"))));
// Or include cross-references in a single-object retrieval
var obj = questions.query.fetchObjectById(questionObjId,
opt -> opt.returnReferences(QueryReference.single("hasCategory",
ref -> ref.returnProperties("title"))));
// Include the cross-references in a query response
var response = await questions.Query.FetchObjects( // Or `Hybrid`, `NearText`, etc.
limit: 2,
returnReferences: [new QueryReference("hasCategory", fields: ["title"])]
);
// Or include cross-references in a single-object retrieval
var obj = await questions.Query.FetchObjectByID(
questionObjId,
returnReferences: [new QueryReference("hasCategory", fields: ["title"])]
);
Delete a cross-reference
Deleting a cross-reference with the same parameters used to define the cross-reference.
If a snippet doesn't work or you have feedback, please open a GitHub issue.
# From the "San Francisco" JeopardyQuestion object, delete the "MUSEUMS" category cross-reference
questions = client.collections.use("JeopardyQuestion")
questions.data.reference_delete(
from_uuid=question_obj_id,
from_property="hasCategory",
to=category_obj_id
)
// From the "San Francisco" JeopardyQuestion object, delete the "MUSEUMS" category cross-reference
const questions = client.collections.use("JeopardyQuestion")
await questions.data.referenceDelete({
fromUuid: questionObjectId,
fromProperty: 'hasCategory',
to: catogoryObjectId
})
sfID := "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
museumsID := "fec50326-dfa1-53c9-90e8-63d0240bd933"
// From the "San Francisco" JeopardyQuestion object, delete the "MUSEUMS" category cross-reference
client.Data().ReferenceDeleter().
WithClassName("JeopardyQuestion").
WithID(sfID).
WithReferenceProperty("hasCategory").
WithReference(client.Data().ReferencePayloadBuilder().
WithClassName("JeopardyCategory").
WithID(museumsID).
Payload()).
Do(ctx)
// Coming soon
// From the "San Francisco" JeopardyQuestion object, delete the "MUSEUMS"
// category cross-reference
questions.data.referenceDelete(
questionObjId, "hasCategory", ObjectReference.uuids(categoryObjId)[0]);
// From the "San Francisco" JeopardyQuestion object, delete the "MUSEUMS" category cross-reference
await questions.Data.ReferenceDelete(
from: questionObjId,
fromProperty: "hasCategory",
to: categoryObjId
);
What happens if the target object is deleted?
What happens if the to object is deleted?
If an object is deleted, cross-references to it will be left intact. A Get query using the inline fragment syntax will correctly retrieve only fields in the existing cross-references objects, but getting the object by ID will show all cross-references, whether the objects they point to exist or not.
Update a cross-reference
The targets of a cross-reference can be updated.
If a snippet doesn't work or you have feedback, please open a GitHub issue.
# In the "San Francisco" JeopardyQuestion object, set the "hasCategory" cross-reference only to "MUSEUMS"
questions = client.collections.use("JeopardyQuestion")
questions.data.reference_replace(
from_uuid=question_obj_id,
from_property="hasCategory",
to=category_obj_id
)
// In the "San Francisco" JeopardyQuestion object, set the "hasCategory" cross-reference only to "MUSEUMS"
const questions = client.collections.use("JeopardyQuestion")
await questions.data.referenceReplace({
fromUuid: questionObjectId,
fromProperty: 'hasCategory',
to: catogoryObjectId
})
sfID := "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
museumsID := "fec50326-dfa1-53c9-90e8-63d0240bd933"
// In the "San Francisco" JeopardyQuestion object, set the "hasCategory" cross-reference only to "MUSEUMS"
client.Data().ReferenceReplacer().
WithClassName("JeopardyQuestion").
WithID(sfID).
WithReferenceProperty("hasCategory").
WithReferences(&models.MultipleRef{
client.Data().ReferencePayloadBuilder().
WithClassName("JeopardyCategory").
WithID(museumsID).
Payload(),
}).
Do(ctx)
// Coming soon
// In the "San Francisco" JeopardyQuestion object, set the "hasCategory"
// cross-reference only to "MUSEUMS"
questions.data.referenceReplace(
questionObjId, "hasCategory", ObjectReference.uuids(categoryObjId)[0]);
// In the "San Francisco" JeopardyQuestion object, set the "hasCategory" cross-reference only to "MUSEUMS"
await questions.Data.ReferenceReplace(
from: questionObjId,
fromProperty: "hasCategory",
to: [categoryObjId]
);
Related pages
- Connect to Weaviate
-
References: REST - /v1/objects
- Retrieve the cross-reference as a part of a query.
Questions and feedback
Have a question or feedback? Here's how to reach us.
