Joins with linking
How to create joins on items within and across content types.
Items are instances of content types. It is possible to join items from the same or other content types within or across sources in a single Optimizely Graph query by linking them with different connection types. This is powerful because it makes it possible to query your content as a graph, although still represented as a hierarchy due to the nature of GraphQL. The advantages of using joins with linking include:
- A single GraphQL query to create joins within and between content types and get a single response, which is much faster and more efficient than building/parsing multiple queries/responses yourself
- Flexibility to establish connections within your data models, add more semantics to the data modeling, and support automated linking in the Optimizely Graph query language
- Filtering and search capabilities are still supported when doing a "linked" query
The system allows linking based on properties (fields) of an item. The property of the item that you want to link from
needs to be specified, as well as the property of an item that you want to link to
. Optimizely Graph allows you to create joins on any field to any field, where the field must be the outer node, i.e., the node that directly contains a value, so you cannot link to nodes that are a composition. A link is established if there is a common value between both properties.
Configuration in the Content Types with API
You can configure links in the Content Types definitions on the root level, similar to languages
and contentTypes
with the property links
. The links
property is optional. The system allows you to specify multiple link types and allows you to define these types with a key like this:
"links": {
"DEFAULT": {
"from": "Tags",
"to": "ContentLink.GuidValue"
},
"AUTHOR": {
"from": "MetaKeywords___searchable",
"to": "Tags"
},
"knows-of": {
"from": "Tags",
"to": "Tags"
},
"friend": {
"from": "FriendOf",
"to": "Name___searchable"
}
}
Optimizely recommends that you always set the DEFAULT
link type, since Optimizely will use this in case the type
is not specified. The values of the properties need to be specified as JSON path.
from
– the property that should be the origin of the linkto
– the property that should be the destination of the link
The properties can be multi-valued, so be of type array. In case you have not specified the DEFAULT
, then the linking will work the same as the Parent/child queries. The GraphQL schema is created by using the keys specified in the Content Types definition, but we create enums by converting the keys to uppercase and replace hyphens with underscore. In case of duplicate keys, the system will use the first one only. So in the example above, we will create the following link type enums: DEFAULT
, AUTHOR
, KNOWS_OF
, FRIEND
.
Query with _link
_link
There is a special field _link
to do the joins on the properties configured. It must be specified as a field within items
. It can consist of an optional input argument called type
that accepts LinkTypes
enum values. These enum values are created based on the keys specified by you in the Content Types definitions.
Note
- The system does not impose any restrictions on the content types, so you can do joins on a query from any content type to any content type.
- A link is established if there is at least 1 common value between the
to
andfrom
, and the common value is defined by you.- We restrict the nesting of
_link
by a depth of 3, so you cannot create joins deeper than this level.
Here is a basic example of a query, where we create a join between instances of StartPage
and BiographyPage
.
{
StartPage {
items {
MetaKeywords
_link {
BiographyPage {
items {
Name
Tags
}
}
}
}
}
}
Examples
Assume we have the above link types defined in our Content Types definitions. Then we could create the following queries to query with this configuration.
If we would query without specifying any link type
, it will use the DEFAULT
link type like this query, where it will join items from StandardPage
within BiographyPage
.
{
BiographyPage {
items {
Name
Tags
_link {
StandardPage(where: { ContentLink: { GuidValue: { exist: true } } }) {
items {
Name
_fulltext
ContentLink {
GuidValue
}
}
}
}
}
}
}
The response would look like this. Note that we created links between the items in the Tags
field with values reference1
and reference2
.
{
"data": {
"BiographyPage": {
"items": [
{
"Name": "Arnold Schwarzenegger",
"Tags": [],
"_link": {
"StandardPage": null
}
},
{
"Name": "Alan Turing",
"Tags": [
"reference1",
"reference2"
],
"_link": {
"StandardPage": {
"items": [
{
"Name": "Standard Page 12",
"_fulltext": [
"Wild Wild West is a 1999 American steampunk Western film co-produced and directed by Barry Sonnenfeld and written by S. S. Wilson and Brent Maddock alongside Jeffrey Price and Peter S. Seaman, from a story penned by brothers Jim and John Thomas. Loosely adapted from The Wild Wild West, a 1960s television series created by Michael Garrison, it is the only production since the television film More Wild Wild West (1980) to feature the characters from the original series. The film stars Will Smith (who previously collaborated with Sonnenfeld on Men in Black two years earlier in 1997) and Kevin Kline as two U.S. Secret Service agents who work together to protect U.S. President Ulysses S. Grant (Kline, in a dual role) and the United States from all manner of dangerous threats during the American Old West.",
"Standard Page 12"
],
"ContentLink": {
"GuidValue": "reference2"
},
"__typename": "StandardPage"
},
{
"Name": "Standard Page 13",
"_fulltext": [
"chi nhánh Cần Thơ",
"Standard Page 13"
],
"ContentLink": {
"GuidValue": "reference1"
},
"__typename": "StandardPage"
}
]
}
}
},
{
"Name": "Marie Curie",
"Tags": [
"reference2"
],
"_link": {
"StandardPage": {
"items": [
{
"Name": "Standard Page 12",
"_fulltext": [
"Wild Wild West is a 1999 American steampunk Western film co-produced and directed by Barry Sonnenfeld and written by S. S. Wilson and Brent Maddock alongside Jeffrey Price and Peter S. Seaman, from a story penned by brothers Jim and John Thomas. Loosely adapted from The Wild Wild West, a 1960s television series created by Michael Garrison, it is the only production since the television film More Wild Wild West (1980) to feature the characters from the original series. The film stars Will Smith (who previously collaborated with Sonnenfeld on Men in Black two years earlier in 1997) and Kevin Kline as two U.S. Secret Service agents who work together to protect U.S. President Ulysses S. Grant (Kline, in a dual role) and the United States from all manner of dangerous threats during the American Old West.",
"Standard Page 12"
],
"ContentLink": {
"GuidValue": "reference2"
},
"__typename": "StandardPage"
}
]
}
}
}
]
}
}
}
You could even define social networks within your data as the following query shows with the FRIEND
link type. Note that is a purely fictional example.
{
BiographyPage {
items {
Name
FriendOf
_link(type: FRIEND) {
BiographyPage {
items {
Name
}
}
}
}
}
}
And here is the response, where we see that Allan Turing is friends with Marie Curie, and vice versa. The other persons do not have a linked friend.
{
"data": {
"BiographyPage": {
"items": [
{
"Name": "Arnold Schwarzenegger",
"FriendOf": [],
"_link": {
"BiographyPage": null
}
},
{
"Name": "Alan Turing",
"FriendOf": [
"Marie Curie"
],
"_link": {
"BiographyPage": {
"items": [
{
"Name": "Marie Curie"
}
]
}
}
},
{
"Name": "Marie Curie",
"FriendOf": [
"Alan Turing"
],
"_link": {
"BiographyPage": {
"items": [
{
"Name": "Alan Turing"
}
]
}
}
}
]
}
}
}
The joins are very flexible, allowing you even to create circular joins as the following example with KNOWS_OF
shows, which links from/to the same field. However, note that we restrict the depth of _link
usage to 3.
{
BiographyPage {
items {
Name
Tags
_link(type: KNOWS_OF) {
BiographyPage {
items {
Name
Tags
__typename
}
}
}
}
}
}
This is how the response could look like:
{
"data": {
"BiographyPage": {
"items": [
{
"Name": "Arnold Schwarzenegger",
"Tags": [],
"_link": {
"BiographyPage": null
}
},
{
"Name": "Alan Turing",
"Tags": [
"reference1",
"reference2"
],
"_link": {
"BiographyPage": {
"items": [
{
"Name": "Alan Turing",
"Tags": [
"reference1",
"reference2"
],
"__typename": "BiographyPage"
},
{
"Name": "Marie Curie",
"Tags": [
"reference2"
],
"__typename": "BiographyPage"
}
]
}
}
},
{
"Name": "Marie Curie",
"Tags": [
"reference2"
],
"_link": {
"BiographyPage": {
"items": [
{
"Name": "Alan Turing",
"Tags": [
"reference1",
"reference2"
],
"__typename": "BiographyPage"
},
{
"Name": "Marie Curie",
"Tags": [
"reference2"
],
"__typename": "BiographyPage"
}
]
}
}
}
]
}
}
}
There is an extra way, that you can add two link types into one query, as a solution to join three tables with different key-pairs as the following example shows:
{
BiographyPage {
items {
Name
Tags
LinkWithDefaultType: _link {
StandardPage {
items {
Name
ContentLink {
GuidValue
}
}
}
}
LinkWithSpecificType: _link(type: KNOWS_OF) {
BiographyPage {
items {
Name
Tags
}
}
}
}
}
}
This is how the response could look like:
{
"data": {
"data": {
"BiographyPage": {
"items": [
{
"LinkWithDefaultType": {
"StandardPage": {
"items": [
{
"ContentLink": {
"GuidValue": "test",
},
"Name": "Page title2",
},
],
},
},
"LinkWithSpecificType": {
"BiographyPage": {
"items": [
{
"Name": "Arnold Schwarzenegger",
"Tags": [
"test",
],
},
{
"Name": "Alan Turing",
"Tags": [
"reference1",
"reference2",
"test",
],
},
],
},
},
"Name": "Arnold Schwarzenegger",
"Tags": [
"test",
],
},
{
"LinkWithDefaultType": {
"StandardPage": {
"items": [
{
"ContentLink": {
"GuidValue": "reference2",
},
"Name": "Standard Page 12",
},
{
"ContentLink": {
"GuidValue": "reference1",
},
"Name": "Standard Page 13",
},
{
"ContentLink": {
"GuidValue": "test",
},
"Name": "Page title2",
},
],
},
},
"LinkWithSpecificType": {
"BiographyPage": {
"items": [
{
"Name": "Arnold Schwarzenegger",
"Tags": [
"test",
],
},
{
"Name": "Alan Turing",
"Tags": [
"reference1",
"reference2",
"test",
],
},
{
"Name": "Marie Curie",
"Tags": [
"reference2",
],
},
],
},
},
"Name": "Alan Turing",
"Tags": [
"reference1",
"reference2",
"test",
],
},
{
"LinkWithDefaultType": {
"StandardPage": {
"items": [
{
"ContentLink": {
"GuidValue": "reference2",
},
"Name": "Standard Page 12",
},
],
},
},
"LinkWithSpecificType": {
"BiographyPage": {
"items": [
{
"Name": "Alan Turing",
"Tags": [
"reference1",
"reference2",
"test",
],
},
{
"Name": "Marie Curie",
"Tags": [
"reference2",
],
},
],
},
},
"Name": "Marie Curie",
"Tags": [
"reference2",
],
},
],
},
},
}
Updated 6 months ago