Cross-references
Overviewโ
You can use cross-references to establish directional relationships between classes, for example from a Book
to its Author
, or from an Author
to their Book
s.
To define a cross-reference, you must:
- At the class level, set up a
cross-reference
property in one class (from
) referring to another (to
) class, then - For individual objects, establish the cross-reference between a particular object of the
from
class, to an object of theto
class, using their ids.
Creating cross-references does not affect object vectors in either direction.
Data setโ
The example for this howto is a dataset consisting of 1000 questions & answers from the popular quiz show "Jeopardy!". The two classes of interest are: JeopardyQuestion
and JeopardyCategory
. Let's pick some objects of interest:
Questions:
{
"answer": "San Francisco",
"question": "This city's Cable Car Museum...",
"_additional": {
"id": "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
}
}
Categories:
[
{
"title": "U.S. CITIES",
"_additional": {
"id": "20ffc68d-986b-5e71-a680-228dba18d7ef"
}
},
{
"title": "MUSEUMS",
"_additional": {
"id": "fec50326-dfa1-53c9-90e8-63d0240bd933"
}
}
]
Add a one-way cross-reference propertyโ
This requires adding one reference property from
a class referring to
another, and adding one cross-reference per object pair.
To add a cross-reference property in the class definition, specify its dataType
as the name of another class in the schema.
For example to specify the cross-reference from JeopardyQuestion
to JeopardyCatgory
:
{
"class": "JeopardyQuestion",
"description": "A Jeopardy! question",
"properties": [
{"name": "question", "dataType": ["text"]},
{"name": "answer", "dataType": ["text"]},
{
"name": "hasCategory",
"dataType": ["JeopardyCategory"],
"description": "The category of the question",
},
],
},
To add a cross-reference from an object to another, specify its source class and id, the property name, and the class and id of the target object. In the example below, we'll add (not set) the "U.S. CITIES" category to the "San Francisco" Q&A (which by default only has the "MUSEUMS" category):
- Python
- TypeScript
sf_id = "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
us_cities_id = "20ffc68d-986b-5e71-a680-228dba18d7ef"
client.data_object.reference.add(
from_class_name="JeopardyQuestion",
from_uuid=sf_id,
from_property_name="hasCategory",
to_class_name="JeopardyCategory",
to_uuid=us_cities_id,
)
await client.data
.referenceCreator()
.withClassName('JeopardyQuestion').withId('00ff6900-e64f-5d94-90db-c8cfa3fc851b')
.withReferenceProperty('hasCategory')
.withReference(
client.data
.referencePayloadBuilder()
.withClassName('JeopardyCategory')
.withId('20ffc68d-986b-5e71-a680-228dba18d7ef')
.payload()
)
.do();
Add two-way cross-referencesโ
This requires adding reference properties in both directions, and adding two cross-reference per object pair (from
A -> to
B and from
B -> to
A).
To define a bidirectional reference between two classes, add a property to each class with the dataType
set to the name of the other class:
JeopardyQuestion
class:
{
"class": "JeopardyQuestion",
"description": "A Jeopardy! question",
"properties": [
{"name": "question", "dataType": ["text"]},
{"name": "answer", "dataType": ["text"]},
{
"name": "hasCategory",
"dataType": ["JeopardyCategory"],
"description": "The category of the question",
},
],
},
JeopardyCategory
class:
{
"class": "JeopardyCategory",
"description": "A Jeopardy! category",
"properties": [
{"name": "title", "dataType": ["text"]},
{
"name": "hasQuestion",
"dataType": ["JeopardyQuestion"],
"description": "Question in this category"
}
]
}
To set up a two-way cross-reference between two objects, set each cross-reference in turn:
- Python
- TypeScript
sf_id = "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
us_cities_id = "20ffc68d-986b-5e71-a680-228dba18d7ef"
# First, add the "hasQuestion" cross-reference property to the JeopardyCategory class
client.schema.property.create("JeopardyCategory", {
"name": "hasQuestion",
"dataType": ["JeopardyQuestion"]
})
# For the "San Francisco" JeopardyQuestion object, add a cross-reference to the "U.S. CITIES" JeopardyCategory object
client.data_object.reference.add(
from_class_name="JeopardyQuestion",
from_uuid=sf_id,
from_property_name="hasCategory",
to_class_name="JeopardyCategory",
to_uuid=us_cities_id,
)
# For the "U.S. CITIES" JeopardyCategory object, add a cross-reference to "San Francisco"
client.data_object.reference.add(
from_class_name="JeopardyCategory",
from_uuid=us_cities_id,
from_property_name="hasQuestion",
to_class_name="JeopardyQuestion",
to_uuid=sf_id,
)
// First, add the "hasQuestion" cross-reference property to the JeopardyCategory class
await client.schema
.propertyCreator()
.withClassName('JeopardyCategory')
.withProperty({
name: 'hasQuestion',
dataType: ['JeopardyQuestion'],
})
.do();
// For the "San Francisco" JeopardyQuestion object, add a cross-reference to the "U.S. CITIES" JeopardyCategory object
await client.data
.referenceCreator()
.withClassName('JeopardyQuestion').withId('00ff6900-e64f-5d94-90db-c8cfa3fc851b')
.withReferenceProperty('hasCategory')
.withReference(
client.data
.referencePayloadBuilder()
.withClassName('JeopardyCategory')
.withId('20ffc68d-986b-5e71-a680-228dba18d7ef')
.payload()
)
.do();
// For the "U.S. CITIES" JeopardyCategory object, add a cross-reference to "San Francisco"
await client.data
.referenceCreator()
.withClassName('JeopardyCategory').withId('20ffc68d-986b-5e71-a680-228dba18d7ef')
.withReferenceProperty('hasQuestion')
.withReference(
client.data
.referencePayloadBuilder()
.withClassName('JeopardyQuestion')
.withId('00ff6900-e64f-5d94-90db-c8cfa3fc851b')
.payload()
)
.do();
Add multiple (one-to-many) cross-referencesโ
To add a one-to-many cross-reference relationship, add to the source object each of the cross-references to the target objects that you need.
For example, to mark that the "San Francisco" Q&A belongs to multiple categories, e.g. "US. CITIES" and "MUSEUMS":
- Python
- TypeScript
sf_id = "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
us_cities_id = "20ffc68d-986b-5e71-a680-228dba18d7ef"
museums_id = "fec50326-dfa1-53c9-90e8-63d0240bd933"
# Add to "San Francisco" the "U.S. CITIES" category
client.data_object.reference.add(
from_class_name="JeopardyQuestion",
from_uuid=sf_id,
from_property_name="hasCategory",
to_class_name="JeopardyCategory",
to_uuid=us_cities_id,
)
# Add the "MUSEUMS" category as well
client.data_object.reference.add(
from_class_name="JeopardyQuestion",
from_uuid=sf_id,
from_property_name="hasCategory",
to_class_name="JeopardyCategory",
to_uuid=museums_id,
)
// Add to "San Francisco" the "U.S. CITIES" category
await client.data
.referenceCreator()
.withClassName('JeopardyQuestion').withId('00ff6900-e64f-5d94-90db-c8cfa3fc851b')
.withReferenceProperty('hasCategory')
.withReference(
client.data
.referencePayloadBuilder()
.withClassName('JeopardyCategory')
.withId('20ffc68d-986b-5e71-a680-228dba18d7ef')
.payload()
)
.do();
// Add the "MUSEUMS" category as well
await client.data
.referenceCreator()
.withClassName('JeopardyQuestion').withId('00ff6900-e64f-5d94-90db-c8cfa3fc851b')
.withReferenceProperty('hasCategory')
.withReference(
client.data
.referencePayloadBuilder()
.withClassName('JeopardyCategory')
.withId('fec50326-dfa1-53c9-90e8-63d0240bd933')
.payload()
)
.withConsistencyLevel('ALL')
.do();
Delete a cross-referenceโ
Deleting a cross-reference requires specifying the parameters that define the cross-reference.
To delete a cross-reference, specify the class, id and cross-reference property name of the source object, and the class and id of the target object:
- Python
- TypeScript
sf_id = "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
museums_id = "fec50326-dfa1-53c9-90e8-63d0240bd933"
# From the "San Francisco" JeopardyQuestion object, delete the "MUSEUMS" category cross-reference
# https://weaviate-python-client.readthedocs.io/en/stable/weaviate.data.references.html#weaviate.data.references.Reference.delete
sf = client.data_object.get(uuid=sf_id, class_name="JeopardyQuestion")
cat = client.data_object.get(uuid=museums_id, class_name="JeopardyCategory")
client.data_object.reference.delete(
from_class_name="JeopardyQuestion",
from_uuid=sf_id,
from_property_name="hasCategory",
to_class_name="JeopardyCategory",
to_uuid=museums_id,
)
// From the "San Francisco" JeopardyQuestion object, delete the "MUSEUMS" category cross-reference
await client.data
.referenceDeleter()
.withClassName('JeopardyQuestion').withId('00ff6900-e64f-5d94-90db-c8cfa3fc851b')
.withReferenceProperty('hasCategory')
.withReference(
client.data
.referencePayloadBuilder()
.withClassName('JeopardyCategory')
.withId('fec50326-dfa1-53c9-90e8-63d0240bd933')
.payload()
)
.do();
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โ
To update the cross-references stored in a property of an object, specify the object's UUID, class name and cross-references property name, as well as the new list of cross-referenced UUIDs and their class (if all objects are of the same class) or classes (one class per each UUID):
- Python
- TypeScript
sf_id = "00ff6900-e64f-5d94-90db-c8cfa3fc851b"
museums_id = "fec50326-dfa1-53c9-90e8-63d0240bd933"
# In the "San Francisco" JeopardyQuestion object, set the "hasCategory" cross-reference only to "MUSEUMS"
# https://weaviate-python-client.readthedocs.io/en/stable/weaviate.data.references.html#weaviate.data.references.Reference.update
client.data_object.reference.update(
from_class_name="JeopardyQuestion",
from_uuid=sf_id,
from_property_name="hasCategory",
to_class_names=["JeopardyCategory"],
to_uuids=[museums_id],
)
// In the "San Francisco" JeopardyQuestion object, set the "hasCategory" cross-reference only to "MUSEUMS"
await client.data
.referenceReplacer()
.withClassName('JeopardyQuestion').withId('00ff6900-e64f-5d94-90db-c8cfa3fc851b')
.withReferenceProperty('hasCategory')
.withReferences([
client.data
.referencePayloadBuilder()
.withClassName('JeopardyCategory')
.withId('fec50326-dfa1-53c9-90e8-63d0240bd933')
.payload(),
])
.do();
Batch creationโ
Cross-references can be created using batches just like data objects. This can be done by using the same batch process, but by adding cross-references to the batch instead of data objects.
Please see the batch import how-to for more on batch imports.
Retrieve cross-referencesโ
Cross-references in Weaviate are not themselves objects, but properties of objects. As such, you can retrieve cross-reference in one of two ways:
- Retrieve the object that it belongs to. This will return the cross-reference as a property of the object.
- Retrieve the cross-reference as a part of a query. Just as you can retrieve any other property of search results, you can retrieve cross-reference properties.
More Resourcesโ
If you can't find the answer to your question here, please look at the:
- Frequently Asked Questions. Or,
- Knowledge base of old issues. Or,
- For questions: Stackoverflow. Or,
- For more involved discussion: Weaviate Community Forum. Or,
- We also have a Slack channel.