Skip to main content

Develop with FastTrack

NumberRangeFacet

The NumberRangeFacet widget displays a range slider for a faceted numeric property in search results. Users can select start and end values to constrain their search.

Note

Users can also constrain a search on numeric values using the BucketRangeFacet widget.

NumberRangeFacet MarkLogic setup

Faceted search in MarkLogic requires a range index on the faceted property. Add a range index for a property in the database configuration using the Admin Interface or one of MarkLogic's programmatic APIs. This screenshot shows a path range index being added to the salary property in the Admin Interface:

A path range index is added to the salary property in the Admin Interface.

With an index in place, a constraint can be configured in the query options of the search application. This will return facets for the property in the search results. For example:

?xml version="1.0" encoding="UTF-8"?>
<options xmlns="http://marklogic.com/appservices/search">
   <constraint name="salary">
        <range type="xs:int" facet="true" collation="">
            <path-index>/envelope/salary</path-index>
        </range>
   </constraint>
   <return-facets>true</return-facets>
</options>

The constraint settings correspond to the settings for the index. return-facets is set to true so that facet results are returned with search results.

This example shows salary facet information returned in the search response:

{
    "snippet-format": "snippet",
    "total": 3,
    "start": 1,
    "page-length": 10,
    "selected": "include",
    "results": [
        {
            "index": 1,
            "uri": "/person/1001.json",
            "path": "fn:doc(\"/person/1001.json\")",
            "score": 0,
            "confidence": 0,
            "fitness": 0,
            "href": "/v1/documents?uri=%2Fperson%2F1001.json",
            "mimetype": "application/json",
            "format": "json",
            "matches": [
                {
                    "path": "fn:doc(\"/person/1001.json\")/object-node()",
                    "match-text": [
                        "person Nerta Hallwood Marketing Manager Active 1985-03-04 104000 person-1001.jpg"
                    ]
                }
            ],
            "extracted": {
                "kind": "array",
                "content": [
                    {
                        "envelope": {
                            "entityType": "person",
                            "id": 1001,
                            "firstName": "Nerta",
                            "lastName": "Hallwood",
                            "title": "Marketing Manager",
                            "status": "Active",
                            "dob": "1985-03-04",
                            "salary": 104000,
                            "image": "person-1001.jpg",
                        }
                    }
                ]
            }
        },
        // ...
    ],
    "facets": {
        "salary": {
            "type": "xs:int",
            "facetValues": [
                {
                    "name": "55000",
                    "count": 1,
                    "value": 55000
                },
                {
                    "name": "87000",
                    "count": 1,
                    "value": 87000
                },
                {
                    "name": "104000",
                    "count": 1,
                    "value": 104000
                }
            ]
        }  
    },
    // ...
}

Example rendering

This example shows the NumberRangeFacet widget. The widget displays a range slider for a faceted salary property. Only documents with a salary property between $67391 and $93401 are returned and displayed.

The NumberRangeFacet widget displays a range slider.

NumberRangeFacet example configuration

This configuration shows the NumberRangeFacet widget imported and configured in a React application:

import { useContext, useState, useEffect } from "react";
import './App.css';
import { MarkLogicContext, SearchBox, ResultsSnippet, NumberRangeFacet } from "ml-fasttrack";
  
function App() {
  
  const context = useContext(MarkLogicContext);
 
  const [numberVals, setNumberVals] = useState([])
  
  const handleSearch = (params) => {
    context.setQtext(params?.q);
  }
 
  const updateNumberRange = (selections) => {
    setNumberVals(selections)
  }
 
  const resetNumberRange = () => {
    context.removeRangeFacetConstraint(numberVals)
    setNumberVals([])
  }
 
  useEffect(() => {
    const debounceTimeout = setTimeout(() => {
      if (numberVals.length !== 0) {
        context.addRangeFacetConstraint(numberVals)
      }
    }, 500)
    return () => {
      clearTimeout(debounceTimeout);
    };
  }, [numberVals]);
  
  return (
    <div className="App">
      <div>
        <SearchBox onSearch={handleSearch}/>
      </div>
      <div style={{display: 'flex', flexDirection: 'row'}}>
          <div style={{width: '640px'}}>
            <ResultsSnippet
              results={context.searchResponse.results}
              paginationFooter={true}
            />
          </div>
          <div>
            {context?.searchResponse?.facets?.salary &&
              <NumberRangeFacet
                title="Salary"
                data={context?.searchResponse?.facets?.salary}
                name="salary"
                separator={'to'}
                minLabel={'Min'}
                maxLabel={'Max'}
                prefix={"$"}
                suffix={""}
                minValue={50000}
                maxValue={150000}
                onChange={updateNumberRange}
                onReset={resetNumberRange}
              />
            }
          </div>
      </div>
    </div>
  );
}
  
export default App;

Code explanation

In the NumberRangeFacet example configuration:

  • The data prop is set to the numeric facet displayed from the search response object.

  • The selections information from the NumberRangeFacet widget is stored in a numberVals state variable by the onChange callback. This information is cleared by the onReset callback.

  • Using a debounceTimeout function avoids unneeded updates to the context object (which results in extra searches on the backend).

NumericRangeFacet API

Prop 

Type 

Description 

data

object

Facet data to display from search results.

title

string

Title for the collapsible header.

subTitle

string

Subtitle for the collapsible header.

name

string

String identifying the facet. Passed as the name value in the onChange event.

separator

string

Separator displayed between the minimum and maximum cards.

minLabel

string

Label for the minimum (start) value.

maxLabel

string

Label for the maximum (end) value.

prefix

string

Optional string to be displayed before the numeric values.

suffix

string

Optional string to be displayed after the numeric values.

containerStyle

CSSProperties

CSS styles applied to the widget.

cardsStyle

CSSProperties

CSS styles applied to the minimum and maximum cards.

step

number

Step by which the number value is incremented/decremented.

minValue

number

Minimum value for the range.

maxValue

number

Maximum value for the range.

onChange

function

Callback function triggered when the range slider values change. It receives an array of selection objects, see NumberRangeFacet callbacks.

onReset

function

Callback function for the reset event.

NumberRangeFacet callbacks

This example shows the selections object passed to the onChange callbacks:

[
    {
        "type": "number",
        "name": "salary",
        "value": 67391,
        "operator": "GE",
        "title": "Salary"
    },
    {
        "type": "number",
        "name": "salary",
        "value": 93401,
        "operator": "LE",
        "title": "Salary"
    }
]