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:
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.
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 theonChange
callback. This information is cleared by theonReset
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" } ]