# Faceting

Facets offer a simple way to allow users to filter their search results. Faceting can be applied to any attribute set in the [product feed](/infinity/developer-guide/the-product-feed.md).

**Adding and Setting Facets**

The following two things are important to keep in mind when working with facets:

1. The first is to specify which facets should be returned in the response, for example to be shown in the frontend. This is done by adding the facets in question to the request. This gives you control over which facets to show. See [Adding facets](#Adding-Facets) for more details.
2. Secondly you can allow users to filter the search request based on facets. This is called applying a facet and it is done by including a list of the attribute values that the request should be filtered on. More on this under [Filtering With Facets](#Filtering-With-Facets).

Note

There is no guarantee that the facets you specify will be returned in the response.

**Datatype**

The datatype of facets must be the same as the datatype of the attribute value in the [product feed](/infinity/developer-guide/the-product-feed.md).

**Dynamic Faceting**

Dynamic faceting means that the Loop54 engine automatically determines which facets, out of the list of specified attributes, are most relevant to show. The relevant facets are chosen based on the context of the search result.

**When can Facets be Applied**

Facets can be applied to the following calls:

* Search
* Category listings
* Related products

The examples on this page show how to add facets to a **search** call. The same logic can be applied to [category listings](/infinity/developer-guide/category-listings.md) by replacing the `search` call with `getEntitiesByAttribute` call and for Java and C# create the `request` object as an instance of `GetEntitiesByAttributeRequest` instead of `SearchRequest`.

**Adding Facets**

This example shows how to specify the facets to include in the response. In this case, we specify `Manufacturer` and `Category`. The response will contain those facets if they are relevant and present for the products in the results along with a count of the number of results that applying the facet would yield.

{% tabs %}
{% tab title="C#" %}

```csharp
// Below is an example of a request - response cycle of an autocomplete request
AutoCompleteRequest request = new AutoCompleteRequest(query);
request.QueriesOptions.Skip = 0;
request.QueriesOptions.Take = 9;
AutoCompleteResponse response = _loop54Client.AutoComplete(request);

var queries = response.Queries.Items.Select(q => q.Query).ToList();

//print out all suggested autocomplete queries
Debug.WriteLine("queries: " + string.Join(", ", queries));
```

C# source code on Github: [AutoCompleteController.cs](https://github.com/LoopFiftyFour/.NET-Connector/blob/master/Loop54.NetCoreCodeExamples/Controllers/AutoCompleteController.cs)
{% endtab %}

{% tab title="Java" %}

```java
// Below is an example of a request - response cycle of an autocomplete request
AutoCompleteRequest request = new AutoCompleteRequest(query);
request.queriesOptions.skip = 0;
request.queriesOptions.take = 9;
AutoCompleteResponse response = loop54Client.autoComplete(request);

List<QueryResult> queryResults = response.queries.items;
List<String> queries = queryResults.stream().map(q->q.query).collect(Collectors.toList());

// print out all suggested autocomplete queries
System.out.println("queries: " + String.join(", ", queries));
```

Java source code on Github: [AutoCompleteController.java](https://github.com/LoopFiftyFour/Java-Connector/blob/master/codeexamples/src/main/java/com/loop54/spring/test/codeexamples/web/AutoCompleteController.java)
{% endtab %}

{% tab title="JavaScript" %}

```javascript
// Below is an example of a request - response cycle of an autocomplete request
var response = client.autoComplete(query, { skip: 0, take: 9 }).then(r => {
  var queries = r.data["queries"].items.map(i => i.query)
  //print out all suggested autocomplete queries
  console.log("queries: " + queries.join())
})
```

JavaScript source code on Github: [autocomplete.js](https://github.com/LoopFiftyFour/JS-Connector/blob/master/codeexamples/autocomplete.js)
{% endtab %}

{% tab title="PHP" %}

```php
/* Request autocompletions for a prefix */
$request = $connector->autocomplete('a')->take(2);

/* Actually perform the request */
$response = $connector->query($request);

echo 'Items starting with prefix:' . PHP_EOL;
/* Print all (unscoped) completions for this prefix */
foreach ($response->getUnscopedResults() as $result) {
echo $result['query'] . PHP_EOL;
}
```

PHP source code on Github: [Simple.php](https://github.com/LoopFiftyFour/PHP-Connector/blob/master/examples/Simple.php)
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="C#" %}

```csharp
// Search with multiple facets
SearchRequest request = new SearchRequest(query);
//Add facets to the search request
request.ResultsOptions.AddDistinctFacet<string>("Manufacturer");
request.ResultsOptions.AddDistinctFacet<string>("Category");
SearchResponse response = _loop54Client.Search(request);
```

C# source code on Github: [FacetingController.cs](https://github.com/LoopFiftyFour/.NET-Connector/blob/master/Loop54.NetCoreCodeExamples/Controllers/FacetingController.cs)
{% endtab %}

{% tab title="Java" %}

```java
// Search with multiple facets
SearchRequest request = new SearchRequest(query);
// Add facets to the search request
request.resultsOptions.addDistinctFacet("Manufacturer");
request.resultsOptions.addDistinctFacet("Category");
SearchResponse response = loop54Client.search(request);
```

Java source code on Github: [FacetingController.java](https://github.com/LoopFiftyFour/Java-Connector/blob/master/codeexamples/src/main/java/com/loop54/spring/test/codeexamples/web/FacetingController.java)
{% endtab %}

{% tab title="JavaScript" %}

```javascript
// Search with multiple facets

// Add facets to the search request
var response = client.search(query, {
  facets: ["Manufacturer", "Category"].map(function (f) {
    return { name: f, attributeName: f, type: "distinct" }
  }),
})
```

JavaScript source code on Github: [faceting.js](https://github.com/LoopFiftyFour/JS-Connector/blob/master/codeexamples/faceting.js)
{% endtab %}

{% tab title="PHP" %}

```php
$request = $connector->search('food');

$request->resultsOptions()
  ->addDistinctFacet('Organic', 'Organic')
  ->addDistinctFacet('Category', 'Category');
```

PHP source code on Github: [Simple.php](https://github.com/LoopFiftyFour/PHP-Connector/blob/master/examples/Simple.php)
{% endtab %}
{% endtabs %}

**Filtering With Facets**

Similar to the previous example we ask that the response contains `Manufacturer` and `Category` and in addition `Organic`and `Price`. Notice that the `Manufacturer` facet is now applied with a list containing the value `specificManufacturer`. This has the effect that the returned result will be filtered on the attribute `Manufacturer` matching the string contained in the variable `specificManufacturer`. Note also that the facet `Price` is a different kind of facet, namely a **RangeFacet** covered by our next example.

{% tabs %}
{% tab title="C#" %}

```
// Search with a distinct facet applied
// The use-case here is e.g. when the user clicks on a specific manufacturer in the search result facet list
SearchRequest request = new SearchRequest(query);

//Add facets to the search request
//And select a specific facet value to filter on
request.ResultsOptions.AddDistinctFacet<string>("Manufacturer", new List<string>() { specificManufacturer });
request.ResultsOptions.AddDistinctFacet<string>("Organic");
request.ResultsOptions.AddDistinctFacet<string>("Category");
request.ResultsOptions.AddRangeFacet<double>("Price");

SearchResponse response = _loop54Client.Search(request);
```

C# source code on Github: [FacetingController.cs](https://github.com/LoopFiftyFour/.NET-Connector/blob/master/Loop54.NetCoreCodeExamples/Controllers/FacetingController.cs)
{% endtab %}

{% tab title="Java" %}

```
// Search with a distinct facet applied
// The use-case here is e.g. when the user clicks on a specific manufacturer in the search result facet list
List<String> selectedManufacturers = new ArrayList<>();
selectedManufacturers.add("MeatNStuff");
SearchRequest request = new SearchRequest(query);

// Add facets to the search request
// And select a specific facet value to filter on
request.resultsOptions.addDistinctFacet("Manufacturer", selectedManufacturers);
request.resultsOptions.addDistinctFacet("Organic");
request.resultsOptions.addDistinctFacet("Category");
request.resultsOptions.addRangeFacet("Price");

SearchResponse response = loop54Client.search(request);
```

Java source code on Github: [FacetingController.java](https://github.com/LoopFiftyFour/Java-Connector/blob/master/codeexamples/src/main/java/com/loop54/spring/test/codeexamples/web/FacetingController.java)
{% endtab %}

{% tab title="JavaScript" %}

```
// Search with a distinct facet applied
// The use-case here is e.g. when the user clicks on a specific manufacturer in the search result facet list

// Add facets to the search request
// And select a specific facet value to filter on
var selectedFacets = {
"Manufacturer": [specificManufacturer],
"Category": [],
"Organic": []
};

var distinctFacets = ["Manufacturer", "Category", "Organic"].map(function(f){return {name:f,attributeName:f,type:"distinct",selected:selectedFacets[f]}});
var rangeFacets = ["Price"].map(function(f){return {name:f,attributeName:f,type:"range"}});

var response = client.search(query, {facets: distinctFacets.concat(rangeFacets)});
```

JavaScript source code on Github: [faceting.js](https://github.com/LoopFiftyFour/JS-Connector/blob/master/codeexamples/faceting.js)
{% endtab %}

{% tab title="PHP" %}

```
$request->resultsOptions()
->addDistinctFacet('Manufacturer', 'Manufacturer', ['Early']);
```

PHP source code on Github: [Simple.php](https://github.com/LoopFiftyFour/PHP-Connector/blob/master/examples/Simple.php)
{% endtab %}
{% endtabs %}

**Range Facets**

We’re now applying the **RangFacet** by passing a parameter consisting of a `max`and `min` value that defines the range within which the attributes of returned products must be.

{% tabs %}
{% tab title="C#" %}

```
// Search with a range facet
// The use-case here is e.g. when the user selects a specific price range in the search result facet list
SearchRequest request = new SearchRequest(query);

//Add facets to the search request
//And select a specific range for a certain facet
request.ResultsOptions.AddDistinctFacet<string>("Manufacturer");
request.ResultsOptions.AddDistinctFacet<string>("Organic");
request.ResultsOptions.AddDistinctFacet<string>("Category");
request.ResultsOptions.AddRangeFacet<double>("Price", new RangeFacetSelectedParameter<double>() { Min = 10, Max = 60 });

SearchResponse response = _loop54Client.Search(request);
```

C# source code on Github: [FacetingController.cs](https://github.com/LoopFiftyFour/.NET-Connector/blob/master/Loop54.NetCoreCodeExamples/Controllers/FacetingController.cs)
{% endtab %}

{% tab title="Java" %}

```
// Search with a range facet
// The use-case here is e.g. when the user selects a specific price range in the search result facet list
SearchRequest request = new SearchRequest(query);

// Add facets to the search request
// And select a specific range for a certain facet
request.resultsOptions.addDistinctFacet("Manufacturer");
request.resultsOptions.addDistinctFacet("Organic");
request.resultsOptions.addDistinctFacet("Category");
request.resultsOptions.addRangeFacet("Price", new RangeFacetParameter.RangeFacetSelectedParameter<Double>() {{ min = 10.0; max = 60.0; }}, null);

SearchResponse response = loop54Client.search(request);
```

Java source code on Github: [FacetingController.java](https://github.com/LoopFiftyFour/Java-Connector/blob/master/codeexamples/src/main/java/com/loop54/spring/test/codeexamples/web/FacetingController.java)
{% endtab %}

{% tab title="JavaScript" %}

```
// Search with a range facet
// The use-case here is e.g. when the user selects a specific price range in the search result facet list

//Add facets to the search request
//And select a specific range for a certain facet
var distinctFacets = ["Manufacturer", "Category", "Organic"].map(function(f){return {name:f,attributeName:f,type:"distinct"}});
var rangeFacets = ["Price"].map(function(f){return {name:f,attributeName:f,type:"range",selected:{min: 10, max: 60}}});

var response = client.search(query, { facets: distinctFacets.concat(rangeFacets)});
```

JavaScript source code on Github: [faceting.js](https://github.com/LoopFiftyFour/JS-Connector/blob/master/codeexamples/faceting.js)
{% endtab %}

{% tab title="PHP" %}

```
$request->resultsOptions()
->addRangeFacet('Price', 'Price', 10, 60);
```

PHP source code on Github: [Simple.php](https://github.com/LoopFiftyFour/PHP-Connector/blob/master/examples/Simple.php)
{% endtab %}
{% endtabs %}

**Rendering Facets**

Finally, this example shows how to render the facets returned in a response. Note that the code starts with a list of desired facets to show and that it then checks for the existence of those facets in the response. Importantly, it does not assume the existence of any facets in the response.

{% tabs %}
{% tab title="C#" %}

```
List<string> distinctFacetsToDisplay = new List<string>() { "Manufacturer", "Category", "Organic" };
foreach (string attributeName in distinctFacetsToDisplay)
{
    var facet = response.Results.GetDistinctFacetByName(attributeName);
    if (facet != null)
    {
        var facetItems = facet.Items;
        if (facetItems.Any())
Debug.WriteLine(attributeName + ": ");
        foreach (var facetItem in facetItems)
        {
Debug.WriteLine(facetItem.GetItem<string>() + ": " + facetItem.Count); // Write the facet name and the number of products in the facet
        }
    }
}
```

C# source code on Github: [CategoryListingController.cs](https://github.com/LoopFiftyFour/.NET-Connector/blob/master/Loop54.NetCoreCodeExamples/Controllers/CategoryListingController.cs)
{% endtab %}

{% tab title="Java" %}

```
List<String> distinctFacetsToDisplay = new ArrayList<String>();
distinctFacetsToDisplay.add("Manufacturer");
distinctFacetsToDisplay.add("Category");
distinctFacetsToDisplay.add("Organic");

for(String attributeName : distinctFacetsToDisplay)
{
  DistinctFacet facet = response.results.getDistinctFacetByName(attributeName);
  if (facet != null)
  {
 List<DistinctFacetItem> facetItems = facet.getItems();
 if (facet.hasValues())
   System.out.println(attributeName + ": ");
 for (DistinctFacetItem facetItem : facetItems)
 {
   System.out.println(facetItem.getItem(String.class) + ": " + facetItem.count); // Write the facet name and the number of products in the facet
 }
  }
}
```

Java source code on Github: [CategoryListingController.java](https://github.com/LoopFiftyFour/Java-Connector/blob/master/codeexamples/src/main/java/com/loop54/spring/test/codeexamples/web/CategoryListingController.java)
{% endtab %}

{% tab title="JavaScript" %}

```
var distinctFacetsToDisplay = ["Manufacturer", "Category", "Organic"];
if(data.results && data.results.facets.length > 0)
{
for (var i in distinctFacetsToDisplay)
{
    var facet = data.results.facets.find(function(f) { return f.type == "distinct" && f.name == distinctFacetsToDisplay[i]; });
    if(facet)
    {
        var facetItems = facet.items;
        if (facetItems && facetItems.length > 0)
            console.log(distinctFacetsToDisplay[i] + ": ");
        for (var j in facetItems)
        {
            console.log(facetItems[j].item + ": " + facetItems[j].count); // Write the facet name and the number of products in the facet
        }
    }
}
}
```

JavaScript source code on Github: [categorylisting.js](https://github.com/LoopFiftyFour/JS-Connector/blob/master/codeexamples/categorylisting.js)
{% endtab %}

{% tab title="PHP" %}

```
$distinctFacetsToDisplay = ['Manufacturer', 'Category', 'Organic'];
$facets = $response->getFacets();
foreach ($facets as $facet) {
if (in_array($facet['name'], $distinctFacetsToDisplay)) {
    echo $facet['name'] . ': ' . PHP_EOL;
    foreach ($facet['items'] as $option) {
        echo '    [' . ($option->selected ? 'X' : ' ') . '] '
            . $option->item . ' (' . $option->count . ')' . PHP_EOL;
    }
}
}
```

PHP source code on Github: [Simple.php](https://github.com/LoopFiftyFour/PHP-Connector/blob/master/examples/Simple.php)
{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.fact-finder.com/infinity/developer-guide/faceting.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
