Information model and API
#
Indices#
AIH Search v1.0The following endpoints are available for Indices in AIH Search v1.0:
#
AIH Search v1.1The following endpoints are available in AIH Search v1.1:
#
Standard IndicesThere are several standard indices with built-in mappings in Search API:
- aih-risks - Risks and their related objects, such as mitigations, risk assessment results, techniques, population items and relationships
- aih-deviations - Deviations and their related objects, such as risks, main systems and equipment
- aih-equipment - Equipment and their related objects, such as plants, main systems, organizations, design objects and deviations
- aih-main-systems - Main systems and their related objects, such as plants, organizations, equipment and deviations
- aih-channels - Channels and their related objects, such as main systems, channel availabilities, data origins and also structure node references
- aih-work-items - Work items and their related objects, such as resources, activities, deviations and primary assets
- aih-structure-node-reference - Objects which have structure node reference, such as risks, deviations, channels, equipment and activities
- activity-inputs - There are 3 indices for activity inputs. They all contain activities and asset references linked with the activity. The difference between the 3 indices is only in the
value
field type- aih-activity-date-inputs - Activity inputs which have format date
- aih-activity-number-inputs - Activity inputs which have format integer or decimal
- aih-activity-text-inputs - All other inputs
- aih-plants - Plants and their related main systems
- aih-main-system-objects - Design objects in main system and their related structure nodes
- aih-activities - Activities and their related objects, such as deviations, main systems and equipment
Standard indices are synchronized daily and additionally updated by AIH events to maintain data consistency.
#
Custom IndexThe Search API v1.1 gives an opportunity to create custom indices. To upload the DLL file and create the index, the following endpoint is used:
- Name
- DisplayName
- ObjectOwnerId - if the field is not set, objectOwner will be the current user
- TriggerSchedule - the schedule for updating the index (how often this job will run)
- File - a DLL file that contains the relevant data for the index
The following endpoint is used to update the custom index:
PUT /Indices
{ "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string", "displayName": "string", "objectOwner": { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "string" }, "triggerSchedule": "string", "type": "custom"}
The type
field cannot be updated as it determines whether the index is custom or standard.
Note : For standard indices, only objectOwner field can be updated.
The following endpoint is used to update the custom index DLL file:
PUT /Indices/{id}/File
The following endpoint is used to delete the custom index:
DELETE /Indices/{id}
- An index cannot be deleted if it is not a custom index.
#
Create Custom IndexThe following NuGet package is required to create a custom index:
- AIH.Search.Abstractions
The class that creates the index must inherit from the CustomIndexBase generic abstract class, and its constructor must contain 2 parameters (first: ICustomServiceProvider
, second: ILogger
).
- CustomIndexBase - generic abstract class included in the AIH.Search.Abstractions NuGet package (
Version >= 6.0.10
). - ICustomServiceProvider - used to get services through dependency injection. It only returns AIH ReadOnly SDK clients (IReadOnlyAssetsClient, IReadOnlyQualityClient, etc.).
- ILogger - Represents a type used to perform logging. The logs will be added to the Search API logs.
Note: Only AIH.Search.Abstractions NuGet package and AIH SDK Clients NuGet packages are allowed to be installed.
Note : The default maximum number of fields that can be added to the custom index is 5000.
#
Code ExampleThis is a code example that creates an index with a mapping and some data.
using AIH.Quality.Clients.v1_0;using AIH.Search.Abstractions;using AIH.Search.Abstractions.CustomServiceProvider;using Microsoft.Extensions.Logging;using OpenSearch.Client;
namespace Example{ public class CreateSomeIndex : CustomIndexBase<SomeIndex> { private readonly IReadOnlyQualityClient _qualityClient;
public CreateSomeIndex(ICustomServiceProvider customServiceProvider, ILogger logger) : base(customServiceProvider, logger) { _qualityClient = customServiceProvider.GetRequiredService<IReadOnlyQualityClient>(); }
public override TypeMappingDescriptor<object> GetMappingDescriptor() { var typeMappingDesctiptor = new TypeMappingDescriptor<object>();
return typeMappingDesctiptor //The alwaysShow meta specifies the fields that should be displayed in FE by default .Meta(x => x.Add("alwaysShow", new List<string>() { "name", "createdDate" })) .Properties<SomeIndex>(ps => ps.Keyword(x => x.Name(x => x.Id).Meta(a => a.Add("displayName", "Id"))) .Keyword(x => x.Name(x => x.Name).Fields(f => f.Text(t => t.Name("asText"))).Meta(a => a.Add("displayName", "Name"))) .Date(x => x.Name(x => x.CreatedDate).Meta(a => a.Add("displayName", "Created date")))
#region Object owner
//The isIdentity meta indicates that the field is an objectOwner name and can be used as "equal to me (myTeams)". .Object<Reference>(o => o.Name(x => x.ObjectOwner) .Properties(ps => ps.Keyword(x => x.Name(x => x.Id).Meta(a => a.Add("displayName", "Id"))) .Keyword(x => x.Name(x => x.Name).Fields(f => f.Text(t => t.Name("asText"))).Meta(a => a.Add("displayName", "Name").Add("isIdentity", "true")))))
#endregion
#region Nested property
.Nested<NestedProp>(x => x.Name(a => a.NestedProps) .Properties(ps => ps.Keyword(x => x.Name(x => x.Name).Fields(f => f.Text(t => t.Name("asText"))).Meta(a => a.Add("displayName", "Name"))) .Keyword(x => x.Name(x => x.Value).Fields(f => f.Text(t => t.Name("asText"))).Meta(a => a.Add("displayName", "Value"))))));
#endregion }
public override async Task<IEnumerable<SomeIndex>> GetEntriesAsync(CancellationToken cancellationToken) { var entries = new List<SomeIndex>();
var deviations = await _qualityClient.DeviationsGetAsync(take: 10, cancellationToken: cancellationToken);
if (deviations.Any()) { foreach (var deviation in deviations) { entries.Add(new SomeIndex { Id = deviation.Id.Value, Name = deviation.ReferenceId, CreatedDate = deviation.CreatedDate, Status = (Status?)deviation.Status,
ObjectOwner = new() { Id = deviation.ObjectOwner.Id, Name = deviation.ObjectOwner.Name, },
NestedProps = deviation.Properties.Select(p => new NestedProp { Name = p.Name, Value = p.Value?.ToString(), }).ToList() }); }
//The logs will be added to the Search API logs _logger.LogInformation("Custom index log: The list of deviations is not empty."); } else { for (int i = 0; i < 10; i++) { var entry = new SomeIndex { Id = Guid.NewGuid(), Name = $"Index {i + 1}", CreatedDate = DateTime.UtcNow, Status = Status.None, ObjectOwner = null };
AddNestedProps(entry, i);
entries.Add(entry); }
//The logs will be added to the Search API logs _logger.LogInformation("Custom index log: The list of deviations is empty."); }
return entries; }
private static void AddNestedProps(SomeIndex entry, int count) { for (int j = 0; j < count; j++) { var nestedProp = new NestedProp { Name = $"Nested prop {j + 1}", Value = null };
entry.NestedProps.Add(nestedProp); } } }
public class SomeIndex { public Guid Id { get; set; } public string Name { get; set; } public DateTime? CreatedDate { get; set; } public Status? Status { get; set; } public Reference ObjectOwner { get; set; } public List<NestedProp> NestedProps { get; set; } = new(); }
public class NestedProp { public string Name { get; set; } public string Value { get; set; } }
public class Reference { public Guid Id { get; set; } public string Name { get; set; } }
[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] public enum Status { New, Active, Closed, Removed, None }}
#
Index resynchronizationIndex synchronization is controlled by the given triggerSchedule (Cron expression) but the index can be resynchronized.
The following endpoint is used to resynchronize the index:
PUT /Indices/{id}/Resynchronization
This is also available in Search v1.0 but the endpoint is different:
PUT /Indices/{indexName}/Resynchronization
#
Saved queriesIn Search API there is an opportunity to save queries that user wants to keep for later usage.
The following endpoints are available for saving queries:
#
Query objectThe information in Query:
- Id
- Name
- ObjectOwner - user who owns the query
- Index - index the query should run for
- Description - query description
- QueryObject - query for search
- Metadata - json field without validation for keeping additional data
For controlling My Actions page in Metadata we have a field called action
{ "action": { "isVisible": true, "order": 1 }}
- IsVisible - if the query is visible in My Actions page
- Order - order within My Actions page
User can execute saved query by calling following endpoint:
POST /Queries/{id}/Execution
This endpoint will execute saved query and will return search result.
Note : To execute a saved query and see index data, the user will need at least 2 permissions: index_read_owned (to access index data) and query_read_owned (to see the saved query).