- Created by Robert Reiner, last modified on 10. Apr 2020
projectdoc Toolbox
Deep links can be used on both sides of predicates in a Where Clause.
- Audience
- Type
- Level of Experience
- Expected Duration
- 15 min
A property reference is defined by ${property name}
. A deep link is an expression where the property reference uses an arrow (->
) to reference another property value: ${A->B}. It implies that the property A expects a document with a property named B. By dereferencing the property value of B replaces the property reference.
Deep links can be used in Select and Where parameters of queries. In a Select parameter the macro simply dereferences the value by following the property chain. Person->Address->City
simply renders the value of the City
property that is referenced by the Person
property via the Address
property.
The Where parameter value is a conjunction of predicates. A predicate has two sides. The left side is the name of a property of a document in the result set. This property must match the right side of the predicate:
Name=Jane
The right side can contain a reference to the current document, the document that contains the macro with the Where parameter. The syntax is slightly different, since we want to express an exact match (see Search Tips for more information on search syntax):
$<Name>=[${Sister->Name}]
Dereferencing the right side is easy, since the right side points to the current document. So this is not different to the task we already solved by using deep links in Selects.
For deep links on the left side of a predicate, the referenced value needs to be materialized. We need to match a document with Lucene and we do not want to dereference a deep link on a collection of possible matches on the returned result set. This might be okay if the number of possible hits is already quite small before we apply the deep link constraints. In case the deep link is the only constraint for the query, this would mean that we need to check every document on Confluence in this way. By materializing the property, we effectively store the result of ${Sister→Name}
by a property name (like Sister's Name
).
In the past materializing properties had to be done manually by adding an additional property to a document at the design time of the document type (or doctype for short). So if you would like the birthday of a person in a stakeholder document, where the stakeholder already has a reference to a single person, the additional property on the stakeholder would use the Display Document Property Ref Macro to conjure the person's birthday value to the stakeholder's property (see Materialize Properties for example).
Since version 4.5 materializing is much easier, but is still required in order to use deep links on the left side of the predicate. This tips gives a short overview over deep links on both sides of the predicate.
Queries
Queries define their constraints with the Where parameter, for instance with the Display Table Macro.
For the following examples the Where parameter consists only of a single predicate for simplicity.
Deep Links on the querying Document's Side
Here are two examples of deep links on the right side of a predicate (or right-side deep links for short). The right side references properties on the document containing the macro.
The first constraint selects on all documents whose Type property is equal to this document's referenced Service's Type.
$<Type>=[${Service->Type}]
We expect the value of the Type properties to be single values. Also the Service property is expected to contain no or only one reference to a service document.
Here is a similar constraint, but this time the Services property may contain multiple services.
$<Type>~(${Services->Type})
In this case the type of documents in the result set must match at least one Type value of the referenced services.
Match List Values with List Operator
In case of multiple values only the list operator (~
) will return the desired result.
$<Type>=[${Services->Type}]
The above predicate will check for an exact match with the whole list of values. Since the indexer stores each of the list elements individually, the exact match on the list will never be a match.
For instance the Services property has the references Service A
with a Type value of A
and Service B
with a Type value of B
, then the predicate above will be resolved to
Type="A, B"
So documents in the result set would require the value A, B
as single type value (not the type A
and/or B
).
In case you actually want to treat a value containing one or more commas as a single value, use the is-single-value control.
Deep Links on the matching Document's Side
Deep links on the left side (or left-side deep links) of a predicate put constraints on the matching document. A name on the left side references a property of documents in the result set.
The following predicate selects on documents who have a Type whose Tags match those of the current document.
$<Type->Tags>~(${Tags})
Since the example above uses the list operator, the Type property could have multiple values. So the syntax does not change in case the property accepts multiple values, like Categories in the next example.
$<Categories->Tags>~(${Tags})
Materialization required!
For these queries to work, the properties on the left side (Type->Tags
respectively Categories->Tags
) are required to be materialized.
For maximum compatibility make sure that in case of list values, the rendering of those value lists is normalized. This is only required for macros that render lists. It is recommended that values are separated by comma.
Materialization has three forms:
Materialization | Description |
---|---|
Materialize the controlled property by an artificial property with the given path. | |
Specify which properties to materialize as artificial properties by doctype. | |
Describes the doctypes model. |
Adding a document property control is typically straight forward. Usually the mat
control is provided in a doctype's template. If you place it in a document instance, then only the property of this instance is materialized.
Specifying the materialization as a space property automatically materializes the property for the referenced doctype for all documents. This only takes effect on document instances that are saved after this space property has been specified. All existing documents need to be reindexed to enable the Lucene indexer to add the materialized properties.
The last option is simply a way to move the materialization directive from the document control to the doctype descriptor. If a user removes the mat
control from a document, the property is no longer materialized for this particular document instance. The problem is that a type specific information is stored with every single instance of that type. While using the doctype descriptor to define materializations is a proper approach, teams deciding to not use doctype descriptors should use the other two approaches. Using space properties is probably easier for teams using doctypes defined by third parties. It is also less error prone to deletion of controls on document instances. But this is a problem inherent to all Confluence pages since there is no connection between the blueprint and its documents after the creation process. Having the control in a template is probably more declarative and easier for teams using their templates in different Confluence environments.
Deep Links on both Sides
Left- and rightside deep links can be combined in queries.
$<Categories->Tags>~(${Categories->Tags})
But remember to materialize the deep link for the left side queries. And do not forget to use the list operator if you are dealing with lists.
Takeaways
So these are the key takeaways of this short tip:
- Deep links allow to dereference property values on both sides of a predicate:
$<Categories->Tags>~(${Categories->Tags})
- Leftside deep links require materialization to work
- When dealing with lists of values, use the list operator:
~
Resources
- Materialize Properties
- Using existing properties from other documents.
- Display Table Macro
- Lists references to projectdoc documents in a table. Allows to select document properties for columns. Also non-list representations are provided.
- Search Tips
- Tips on specifying search queries for Lucene. This also applies to projectdoc's query macros.
- Display Document Property Ref Macro
- Displays a document property from a referenced document.