Chapter 2 - Metadata Mojo¶
This tutorial is based on the metadata_mojo.js example, which can be found in the TRAC GitHub Repository under examples/apps/javascript.
It may be helpful to read the metadata model overview before starting this tutorial.
Searching¶
Metadata searches allow you to search the metadata database using tag attributes. Any and all tag attributes are searchable. A selection of standard search operators are available, which can be combined in logical expressions to form fine-grained searches. Any search can be executed “as-of” a previous point in time, to provide a consistent view of the historical state of the platform.
Find a single object¶
Starting with the simplest search, let’s look for an object based on a single tag attribute.
In this example we’re looking for a particular type of schema using a single search term,
schema_type = "customer_records"
.
Let’s create a request for this search:
28 const searchRequest = tracdap.api.MetadataSearchRequest.create({
29
30 tenant: "ACME_CORP",
31 searchParams: {
32
33 objectType: tracdap.ObjectType.SCHEMA,
34
35 search: { term: {
36
37 attrName: "schema_type",
38 attrType: tracdap.STRING,
39 operator: tracdap.SearchOperator.EQ,
40 searchValue: { stringValue: "customer_records" }
41 }}
42 }
43 })
In the SearchParameters
we set the type of object to search
for, and provide a search expression containing a single search term.
To execute the search we use the search()
method of the
TracMetadataApi
.
48export function findFirst(searchRequest) {
49
50 return metaApi.search(searchRequest).then(response => {
51
52 const nResults = response.searchResult.length;
53
54 if (nResults === 0)
55 throw new Error("No matching search results");
56
57 console.log(`Got ${nResults} search result(s), picking the first one`);
58
59 return response.searchResult[0].header;
60 });
61}
This method returns a search result, which is a list of tags without their definition bodies. In a real-world scenario, the list might be displayed in a search grid with the attributes as columns, so the user can look through the results and select the one they want. For this example we just select the first result.
We return the header
field of the selected objet, which is a TagHeader
object that can be used as an object ID. For example, this ID could be used in the
Loading objects example in the previous tutorial, to load tag with its full definition.
Logical search expressions¶
Search terms can be combined to form logical expressions, where each expression is either a single term or a logical combination of other expressions.
Here is a simple example, starting with expression for the single term from the previous example:
63export function logicalSearch() {
64
65 const schemaTypeCriteria = tracdap.metadata.SearchExpression.create({
66 term: {
67 attrName: "schema_type",
68 attrType: tracdap.STRING,
69 operator: tracdap.SearchOperator.EQ,
70 searchValue: { stringValue: "customer_records" }
71 }
72 });
Now a second expression, we want to know if the business division attribute is one of the business divisions we are interested in:
74 const businessDivisionCriteria = tracdap.metadata.SearchExpression.create({
75 term: {
76 attrName: "business_division",
77 attrType: tracdap.STRING,
78 operator: tracdap.SearchOperator.IN,
79 searchValue: { arrayValue: {
80 items: [
81 { stringValue: "WIDGET_SALES" },
82 { stringValue: "WIDGET_SERVICES" },
83 { stringValue: "WIDGET_RND_ACTIVITIES" }
84 ]
85 }}
86 }
87 });
See the documentation for SearchOperator
for the
list of all available search operators.
Now let’s create a logical expression, which combines the two previous expressions:
89 const logicalSearch = tracdap.metadata.SearchExpression.create({
90 logical: {
91 operator: tracdap.LogicalOperator.AND,
92 expr: [
93 schemaTypeCriteria,
94 businessDivisionCriteria
95 ]
96 }
97 });
Any number of expressions can be added to the AND
clause without nesting, since AND
is
an associative operation. The OR
operator works the same way. If you want to combine AND
and OR
operations then nesting is required (a single search term with the IN
operator
can often remove the need to use OR
). For the logical NOT
operator, list of expressions
must contain exactly one expression (again, most search operators have negative equivalents which
remove the need to use NOT
).
Once the top level search expression is built, it can be included in a search request and used
to call the search()
method of the
TracMetadataApi
.
99 const searchRequest = tracdap.api.MetadataSearchRequest.create({
100
101 tenant: "ACME_CORP",
102 searchParams: {
103 objectType: tracdap.ObjectType.SCHEMA,
104 search: logicalSearch
105 }
106 });
107
108 return findFirst(searchRequest);
109}
More Mojo¶
Several other metadata features are available in the current release of TRAC, including:
The ability to update objects and retrieve the full history of object versions
Tags can be updated independently of their objects, with a full history of tag updates
Point-in-time searches and selectors, providing a historical snapshot across all of TRAC’s metadata
The metadata type system, which allows attributes to be defined with any supported data type
Multi-valued tag attributes
These features can be explored by looking at the documentation for the
TracMetadataApi
and the Metadata Listing
.