AWS Security Blog

How to Search More Efficiently in Amazon Cloud Directory

Using Amazon Cloud Directory, you can build flexible, cloud-native directories for organizing hierarchies of data along multiple dimensions. And now, you can search more efficiently by searching across only a subset of objects in your directory. For example, instead of searching through all of the employees in a company directory built using Cloud Directory, you can choose to search only full-time employees or contractors.

To search across such a subset of objects, you must first create a facet-based index. A facet is a set of attributes defined in a schema that is associated with a directory object. Using facets, you can create different object types in your directory. For instance, you can create different facets for full-time employees and contractors in a schema and then create full-time employee objects and contractor objects. You then can create an index of all the objects that include a specific facet and search those objects more efficiently.

In this blog post, I show how you can create a facet-based index in Cloud Directory to more efficiently search for objects in your directory.

Scenario: Searching a company directory for a specific employee type

Let’s say a company called AnyCompany wants to be able to efficiently search in Cloud Directory for information about its full-time employees and contractors. To do this, AnyCompany must create a company directory using Cloud Directory. (If AnyCompany already had a company directory using Cloud Directory, they could use that directory instead.) AnyCompany starts by creating DirectorySchema, which is a schema that includes three facets: FullTimeEmployeeFacet, ManagerFacet, and ContractorFacet.

Schema: DirectorySchema

Facet: FullTimeEmployeeFacet
Attribute: EmployeeId, type: Integer
Attribute: Name, type: String
Attribute: EMail, type: String
Attribute: Salary, type: Integer

Facet: ManagerFacet
Attribute: Budget, type: Integer
Attribute: LeaveApproval, type: Boolean

Facet: ContractorFacet
Attribute: Name, type: String
Attribute: EMail, type: String
Attribute: VendorCompany, type: String
Attribute: VendorPO, type: Integer

The following diagram is a visual representation of AnyCompany’s company directory, and it includes full-time employees and contractors in a reporting hierarchy. The full-time employees are shown in blue nodes and the contractors are shown in green nodes. The directory’s three facets are shown as they correspond to full-time employees, managers, and contractors.

AnyCompany's company directory

To more efficiently search your directory, follow these steps:

  1. Create a facet-based index that includes the facets you want to use when searching.
  2. Populate the index with the appropriate employee objects.
  3. List all the objects in the index.
  4. List objects in the index that include a specific facet.

1. Create a facet-based index that includes the facets you want to use when searching

The following code example creates a facet-based index of the employee objects in the directory. Cloud Directory currently supports only simple indexes, which means that an index object can only store one type of value, such as a facet.

     // Create an index
     // <region> indicates an AWS Region value such as “us-east-1”
     // <accountId> indicates your AWS account ID
     // <directoryId> indicates your Cloud Directory ID

     // The schemaArn points to the specific schema, which is DirectorySchema
     String schemaArn = "arn:aws:clouddirectory:<region>:<accountId>:directory/<directoryId>/schema/DirectorySchema/1.0" ;

     // I define attributes that I want to use for indexing. In this case, I use “facets” to define an 
     // attribute for indexing. This is a hard-coded value that is defined by Cloud Directory.

     AttributeKey indexAttributeKey = new AttributeKey()    
        .withSchemaArn(schemaArn)
        .withFacetName("facets")
        .withName("facets") ;

     List<AttributeKey> orderedIndexedAttributeList = new ArrayList<AttributeKey>() ;

     orderedIndexedAttributeList.add(indexAttributeKey) ;

     // The directoryArn points to the specific directory that I am working on 
     String directoryArn = "arn:aws:clouddirectory:<region>:<accountId>:directory/<directoryId>" ;

     // I create the index request and pass in the directoryArn and my attribute list. 
     // Because I am defining the facetIndex at the root of my directory, my parentReference is the root of the directory
     // For LinkName, I have defined “MyFacetIndex,” as shown in the diagram

     ObjectReference dirRoot = new ObjectReference().withSelector("/"); // Directory root
	 
     CreateIndexRequest createRequest = new CreateIndexRequest()
        .withDirectoryArn(directoryArn)
        .withOrderedIndexedAttributeList(orderedIndexedAttributeList)
        .withIsUnique(false)
        .withParentReference(dirRoot)  // Attach to directory root
        .withLinkName("MyFacetIndex") ;

     // I assign the indexed object to facetIndex 
     CreateIndexResult facetIndexResult = cloudDirectoryClient.createIndex(createRequest) ;
     ObjectReference facetIndex = new ObjectReference().withSelector(facetIndexResult.getObjectIdentifier());

2. Populate the index with the appropriate employee objects

Next, I add all the objects that I want to include in the index. The following code example adds objects to facetIndex.

     // I assume userObj1 is “Tim”. The following code adds “Tim” to the index. 

     // Create an index attach request with the directory, facet, and object details
     AttachToIndexRequest indexAttachRequest = new AttachToIndexRequest()
         .withDirectoryArn(directoryArn)
         .withIndexReference(facetIndex)
         .withTargetReference(userObj1) ;

     // Add the object to the index
     cloudDirectoryClient.attachToIndex(indexAttachRequest) ;

     // You can follow the same code pattern to add other full-time employee and contractor objects to the index. 

3. List all the objects in the index

Now, I can query my directory efficiently for the set of objects I have in facetIndex. The following code example returns all the objects in your index.

     // List all objects in the facet-based index 
     ListIndexResult listResults = cloudDirectoryClient.listIndex(new ListIndexRequest()
         .withDirectoryArn(directoryArn)
         .withIndexReference(facetIndex)) ;

4. List objects in the index that include a specific facet

I can add a filter for retrieving subsets of objects in the index that contain a specific facet. The following code example shows how to add a filter to the query so that only objects that contain the facet FullTimeEmployeeFacet are returned.

     // I choose the specific facet I will use for filtering my query and get all objects that contain this facet in them.
	
	 String filterString = "DirectorySchema/1.0/FullTimeEmployeeFacet" ;
	 TypedAttributeValue filterStringValue = new TypedAttributeValue().withStringValue(filterString);
	 
     // I define the filter range and mention both the start mode and end mode as inclusive because I will query for a specific facet 
	 ObjectAttributeRange objectAttributeRange = new ObjectAttributeRange()
			.withAttributeKey(new AttributeKey()
			.withFacetName("facets")
			.withName("facets") 
			.withSchemaArn(schemaArn))
			.withRange(new TypedAttributeValueRange()
					.withStartMode(RangeMode.INCLUSIVE)
					.withStartValue(filterStringValue)
					.withEndMode(RangeMode.INCLUSIVE)
					.withEndValue(filterStringValue)) ; // Query for objects with FullTimeEmployeeFacet which is defined in filterString

     // List the index results

	 ListIndexResult filteredResults = cloudDirectoryClient.listIndex(new ListIndexRequest()
	    .withDirectoryArn(directoryArn)
	    .withIndexReference(facetIndex)
	    .withRangesOnIndexedValues(objectAttributeRange)) ;

Using this subset of objects, I can now search for a specific employee without searching across all the objects in my directory.

Summary

You can use facet-based indexing to search your directory more efficiently by searching across only a subset of objects in of your directory. For more information about this feature, see Indexing and Search.

If you have comments about this blog post, submit them in the “Comments” section below. If you have questions about implementing the solution in this blog post, start a new thread in the Directory Service forum or contact AWS Support.

– Mahendra