Skip to main content

Getting Started with Optic

Building Results-with-Facets Queries

Faceting results is a powerful feature of MarkLogic search capabilities that you will want to explore. Facets enrich search user interfaces by effectively generating metadata about the query, helping your end users to explore data more efficiently. See Including Facets in Search Results in the Search Developer’s Guide for more detailed information than we provide here.

Faceting results amounts to defining a query to evaluate for results then reevaluating it to discover how many results fall into specified categories.

We want to retrieve all the data for employees hired on or after January 1, 2022 as in With a Date Constraint. But we also want to see how these employees are distributed across departments and/or states.

An Optic query like this one creates an output object containing a result with two facets, Departments and States:

const op = require('/MarkLogic/optic');

// Reuse the same constrained query for multiple tasks:
const query = op.fromView('Employee', 'Profile')
              .where(op.ge(op.col('HiredDate'), xs.date('2022-01-01')))

// Fetch the view results:
const results = query.offsetLimit(0, 100).result();

// Fetch facets for quick aggregations:
const facets = 
    query.facetBy([
      op.namedGroup('Departments', 'Department'),
      op.namedGroup('States', 'State')
    ])
    .offsetLimit(0, 100)
    .result()

// Build an Output Object:
const output = {
  'results': results,
  'facets': facets
}

output

We used this query to produce a results array containing up to 100 employees hired on or after January 1, 2022 and a facets object containing the department and state facet arrays.

There are several sections to this query:

  • The part of the original query from With a Date Constraint that finds employees hired on or after a certain date, stored as query.

  • The result of that query, limited to 100 results, stored as results.

  • The generation of the facets, stored as facets, explained in more detail below.

  • The building of the output object containing both the results and the facets, stored as output.

Here are the details of the faceting functions:

  • The Operator Function facetBy() takes as many namedGroup() functions as needed, creating a facet for each one.

  • The Operator Function namedGroup() defines an array in the first parameter to hold counts for each unique value encountered in the column specified in the second parameter.

There are several parts to the result:

  • A 23-row x 85-column row sequence called results containing all 23 view columns for each of the 85 matching employees. Here are the first, second, and last rows:

    {
      "results": [
        {
          "Employee.Profile.GUID": "86148084-f46f-46ba-a5b7-24748629a611", 
          "Employee.Profile.HiredDate": "2022-06-07",              // HiredDate
          "Employee.Profile.Gender": "male", 
          "Employee.Profile.Title": "Mr.", 
          "Employee.Profile.GivenName": "Michael", 
          "Employee.Profile.MiddleInitial": "S", 
          "Employee.Profile.Surname": "Dandridge", 
          "Employee.Profile.StreetAddress": "1012 Union Street", 
          "Employee.Profile.City": "Seattle", 
          "Employee.Profile.State": "WA", 
          "Employee.Profile.ZipCode": "98107", 
          "Employee.Profile.Country": "US", 
          "Employee.Profile.EmailAddress": "MichaelSDandridge@superrito.com", 
          "Employee.Profile.TelephoneNumber": "206-784-1532", 
          "Employee.Profile.TelephoneCountryCode": "1", 
          "Employee.Profile.Birthday": "2/11/61", 
          "Employee.Profile.NationalID": "535-09-2679", 
          "Employee.Profile.Point": "47.675446,-122.41084", 
          "Employee.Profile.BaseSalary": 79072, 
          "Employee.Profile.Bonus": 7907, 
          "Employee.Profile.Department": "R&D", 
          "Employee.Profile.Status": "Active - Regular Exempt (Full-time)", 
          "Employee.Profile.ManagerGUID": "695fdc37-42f1-4c19-9ba1-c4fe87454041"
        }, 
        {
          "Employee.Profile.GUID": "82f2a62f-ff1f-4657-bbef-3ae2a032851f", 
          "Employee.Profile.HiredDate": "2022-08-12",              // HiredDate
          "Employee.Profile.Gender": "female", 
          "Employee.Profile.Title": "Mrs.", 
          "Employee.Profile.GivenName": "Bettye", 
          "Employee.Profile.MiddleInitial": "J", 
          "Employee.Profile.Surname": "Henley", 
          "Employee.Profile.StreetAddress": "3838 Braxton Street", 
          "Employee.Profile.City": "Sheridan", 
          "Employee.Profile.State": "IL", 
          "Employee.Profile.ZipCode": "60551", 
          "Employee.Profile.Country": "US", 
          "Employee.Profile.EmailAddress": "BettyeJHenley@teleworm.us", 
          "Employee.Profile.TelephoneNumber": "815-496-5820", 
          "Employee.Profile.TelephoneCountryCode": "1", 
          "Employee.Profile.Birthday": "7/30/59", 
          "Employee.Profile.NationalID": "325-42-8057", 
          "Employee.Profile.Point": "41.463001,-88.609024", 
          "Employee.Profile.BaseSalary": 33752, 
          "Employee.Profile.Bonus": 3375, 
          "Employee.Profile.Department": "Sales", 
          "Employee.Profile.Status": "Active - Regular Exempt (Full-time)", 
          "Employee.Profile.ManagerGUID": "07bb968f-e95e-4c40-8889-d88ba6b369d0"
        }, 
    // ... 82 other results ...
        {
          "Employee.Profile.GUID": "8b7f98f0-60f2-4e40-bd01-bb0e2b30d99e", 
          "Employee.Profile.HiredDate": "2022-11-01",               // HiredDate
          "Employee.Profile.Gender": "female", 
          "Employee.Profile.Title": "Mrs.", 
          "Employee.Profile.GivenName": "Shirley", 
          "Employee.Profile.MiddleInitial": "D", 
          "Employee.Profile.Surname": "Heath", 
          "Employee.Profile.StreetAddress": "3236 Zappia Drive", 
          "Employee.Profile.City": "Lexington", 
          "Employee.Profile.State": "KY", 
          "Employee.Profile.ZipCode": "40507", 
          "Employee.Profile.Country": "US", 
          "Employee.Profile.EmailAddress": "ShirleyDHeath@superrito.com", 
          "Employee.Profile.TelephoneNumber": "859-357-3731", 
          "Employee.Profile.TelephoneCountryCode": "1", 
          "Employee.Profile.Birthday": "9/17/38", 
          "Employee.Profile.NationalID": "406-84-3068", 
          "Employee.Profile.Point": "38.028934,-84.538956", 
          "Employee.Profile.BaseSalary": 17920, 
          "Employee.Profile.Bonus": 1792, 
          "Employee.Profile.Department": "Sales", 
          "Employee.Profile.Status": "Active - Regular Exempt (Full-time)", 
          "Employee.Profile.ManagerGUID": "07bb968f-e95e-4c40-8889-d88ba6b369d0"
        }
      ],
  • Two sets of facets:

    • The Departments facet array: Each object's first property contains a unique value encountered in the result's Department column. The second property contains the number of times that value was encountered. So, this facet effectively provides the number of employees in each department. Here are all 5 Department facets:

        "facets": {
          "Departments": [
            {
              "Department": "R&D", 
              "count": 30
            }, 
            {
              "Department": "Sales", 
              "count": 24
            }, 
            {
              "Department": "Engineering", 
              "count": 15
            }, 
            {
              "Department": "Marketing", 
              "count": 13
            }, 
            {
              "Department": "Training", 
              "count": 3
            }
          ], 
    • The States facet array: Each object's first property contains a unique value encountered in the result's State column. The second property contains the number of times that value was encountered. So, this facet effectively provides the number of employees in each state. Here are the first 4 and last 1 of the 33 State facets:

          "States": [
            {
              "State": "WA", 
              "count": 4
            }, 
            {
              "State": "IL", 
              "count": 6
            }, 
            {
              "State": "MI", 
              "count": 2
            }, 
            {
              "State": "OR", 
              "count": 1
            }, 
      // ... 28 other results ...
            {
              "State": "KS", 
              "count": 1
            }
          ]
        }
      }
  • These facets allow your end user to not only find out how many new employees are in particular departments or particular states but also to find out how many new employees in particular departments are also in particular states and vice versa.

  • You can return just the facets without the query results.