Research
Recent Trends in Malicious Packages Targeting Discord
The Socket research team breaks down a sampling of malicious packages that download and execute files, among other suspicious behaviors, targeting the popular Discord platform.
algoliasearch-helper
Advanced tools
Readme
Coming from V1 (or js client v2)? Read the migration guide to the new version of the Helper.
This module is the companion of the algolia/algoliasearch-client-js. It helps you keep track of the search parameters and provides a higher level API.
This is the library you will need to easily build a good search UX like our instant search demo.
A small example that uses Browserify to manage modules.
var algoliasearch = require('algoliasearch');
var algoliasearchHelper = require('algoliasearch-helper');
var client = algoliasearch('appId', 'apiKey');
var helper = algoliasearchHelper(client, 'indexName', {
facets: ['mainCharacterFirstName', 'year'],
disjunctiveFacets: ['director']
});
helper.on('result', function(data){
console.log(data.hits);
});
helper.addDisjunctiveRefine('director', 'Clint Eastword');
helper.addDisjunctiveRefine('director', 'Sofia Coppola');
helper.addNumericRefinement('year', '=', 2003);
// Search for any movie filmed in 2003 and directed by either C. Eastwood or S. Coppola
helper.search();
There is also a complete JSDoc
<script>
tagUse our jsDelivr build:
<script src="//cdn.jsdelivr.net/algoliasearch.helper/2/algoliasearch.helper.min.js"></script>
npm install algoliasearch-helper
bower install algoliasearch-helper
var helper = algoliasearchHelper(client, 'indexName'/*, parameters*/);
modify the parameters of the search (usually through user interactions)
helper.setQuery('iphone').addRefine('category', 'phone')
trigger the search (after all the modification have been applied)
helper.search()
read the results (with the event "result" handler) and update the UI with the results
helper.on('result', function(results) { updateUI(results); });
go back to 1
AlgoliasearchHelper: the helper. Keeps the state of the search, makes the queries and calls the handlers when an event happen.
SearchParameters: the object representing the state of the search. The current state is stored in helperInstance.state
.
SearchResults: the object in which the Algolia answers are transformed into. This object is passed to the result event handler. An example of SearchResults in JSON is available at the end of this readme
The search is triggered by the search()
method.
It takes all the previous modifications to the search and uses them to create the queries to Algolia. The search parameters are immutable.
Example:
var helper = algoliasearchHelper(client, indexName);
// Let's monitor the results with the console
helper.on('result', function(content) {
console.log(content);
});
// Let's make an empty search
// The results are all sorted using the dashboard configuration
helper.search();
// Let's search for "landscape"
helper.setQuery('landscape').search();
// Let's add a category "photo"
// Will make a search with "photo" tag and "landscape" as the query
helper.addTag('photo').search();
The helper is an Event Emitter.
result
: get notified when new results are received. The handler function will receive
two objects (SearchResults
and SearchParameters
).
error
: get notified when errors are received from the API.
change
: get notified when a property has changed in the helper
result
eventhelper.on('result', updateTheResults);
result
event oncehelper.once('result', updateTheResults);
result
listenershelper.removeListener('result');
helper.setQuery('fruit').search();
Facets are filters to retrieve a subset of an index having a specific value for a given attribute. First you need to define which attribute will be used as a facet in the dashboard: https://www.algolia.com/explorer#?tab=display
var helper = algoliasearchHelper(client, indexName, {
facets: ['ANDFacet']
});
helper.addRefine('ANDFacet', 'valueOfANDFacet').search();
helper.removeRefine('ANDFacet', 'valueOfANDFacet').search();
var helper = algoliasearchHelper(client, indexName, {
disjunctiveFacets: ['ORFacet']
});
helper.addDisjunctiveRefine('ORFacet', 'valueOfORFacet').search();
helper.removeDisjunctiveRefine('ORFacet', 'valueOfORFacet').search();
filter so that we do NOT get a given category
var helper = algoliasearchHelper(client, indexName, {
facets: ['ANDFacet']
}).search();
helper.addExclude('ANDFacet', 'valueOfANDFacetToExclude');
helper.removeExclude('ANDFacet', 'valueOfANDFacetToExclude');
Filter over numeric attributes with math operations like =
, >
, <
, >=
, <=
. Can be used for numbers and dates (if converted to timestamp)
var helper = algoliasearchHelper(client, indexName, {
disjunctiveFacets: ['numericFacet']
});
helper.addNumericRefinement('numericFacet', '=', '3').search();
helper.removeNumericRefinemetn('numericFacet', '=', '3').search();
Hierarchical facets are useful to build such navigation menus:
| products
> fruits
> citrus
| strawberries
| peaches
| apples
Here, we refined the search this way:
To build such menu, you need to use hierarchical faceting:
var helper = algoliasearchHelper(client, indexName, {
hierarchicalFacets: [{
name: 'products',
attributes: ['categories.lvl0', 'categories.lvl1']
}]
});
Given your objects looks like this:
{
"objectID": "123",
"name": "orange",
"categories": {
"lvl0": "fruits",
"lvl1": "fruits > citrus"
}
}
And you refine products
:
helper.toggleRefine('products', 'fruits > citrus');
You will get a hierarchical presentation of your facet values: a navigation menu of your facet values.
helper.on('result', function(data){
console.log(data.hierarchicalFacets[0]);
// {
// 'name': 'products',
// 'count': null,
// 'isRefined': true,
// 'path': null,
// 'data': [{
// 'name': 'fruits',
// 'path': 'fruits',
// 'count': 1,
// 'isRefined': true,
// 'data': [{
// 'name': 'citrus',
// 'path': 'fruits > citrus',
// 'count': 1,
// 'isRefined': true,
// 'data': null
// }]
// }]
// }
});
To ease navigation, we always:
fruits > citrus > *
: n + 1)fruits > citrus
=> fruits
: n -1) categoriesvar helper = algoliasearchHelper(client, indexName, {
hierarchicalFacets: [{
name: 'products',
attributes: ['categories.lvl0', 'categories.lvl1'],
separator: '|'
}]
});
helper.toggleRefine('products', 'fruits|citrus');
Would mean that your objects look like so:
{
"objectID": "123",
"name": "orange",
"categories": {
"lvl0": "fruits",
"lvl1": "fruits|citrus"
}
}
The default sort for the hierarchical facet view is: isRefined:desc (first show refined), name:asc (then sort by name)
.
You can specify a different sort order by using:
var helper = algoliasearchHelper(client, indexName, {
hierarchicalFacets: [{
name: 'products',
attributes: ['categories.lvl0', 'categories.lvl1'],
sortBy: ['count:desc', 'name:asc'] // first show the most common values, then sort by name
}]
});
The available sort tokens are:
var helper = algoliasearchHelper(client, indexName, {
hierarchicalFacets: [{
name: 'products',
attributes: ['categories.lvl0', 'categories.lvl1'],
separator: '|'
}]
});
helper.toggleRefine('products', 'fruits|citrus');
var breadcrumb = helper.getHierarchicalFacetBreadcrumb('products');
console.log(breadcrumb);
// ['fruits', 'citrus']
console.log(breadcrumb.join(' | '));
// 'fruits | citrus'
helper.clearRefinements().search();
helper.clearRefinements('ANDFacet').search();
helper.clearRefinements(function(value, attribute, type) {
return type === 'exclude' && attribute === 'ANDFacet';
}).search();
Tags are an easy way to do filtering. They are based on a special attribute in the records named _tags
, which can be a single string value or an array of strings.
helper.addTag('landscape').search();
helper.removeTag('landscape').search();
helper.clearTags().search();
helper.getCurrentPage();
helper.setCurrentPage(3).search();
Index can be changed. The common use case is when you have several slaves with different sort order (sort by relevance, price or any other attribute).
helper.setIndex('index_orderByPrice').search();
var currentIndex = helper.state.index;
There are lots of other parameters you can set.
var helper = algoliasearchHelper(client, indexName, {
hitsPerPage: 50
});
helper.setQueryParameter('hitsPerPage', 20).search();
Name |
Type |
Description |
advancedSyntax |
boolean |
Enable the advanced syntax. |
allowTyposOnNumericTokens |
boolean |
Should the engine allow typos on numerics. |
analytics |
boolean |
Enable the analytics |
analyticsTags |
string |
Tag of the query in the analytics. |
aroundLatLng |
string |
Center of the geo search. |
aroundLatLngViaIP |
boolean |
Center of the search, retrieve from the user IP. |
aroundPrecision |
number |
Precision of the geo search. |
aroundRadius |
number |
Radius of the geo search. |
attributesToHighlight |
string |
List of attributes to highlight |
attributesToRetrieve |
string |
List of attributes to retrieve |
attributesToSnippet |
string |
List of attributes to snippet |
disjunctiveFacets |
Array.<string> |
All the declared disjunctive facets |
distinct |
boolean |
Remove duplicates based on the index setting attributeForDistinct |
facets |
Array.<string> |
All the facets that will be requested to the server |
getRankingInfo |
integer |
Enable the ranking informations in the response |
hitsPerPage |
number |
Number of hits to be returned by the search API |
ignorePlurals |
boolean |
Should the plurals be ignored |
insideBoundingBox |
string |
Geo search inside a box. |
maxValuesPerFacet |
number |
Number of values for each facetted attribute |
minWordSizefor1Typo |
number |
Number of characters to wait before doing one character replacement. |
minWordSizefor2Typos |
number |
Number of characters to wait before doing a second character replacement. |
optionalWords |
string |
Add some optional words to those defined in the dashboard |
page |
number |
The current page number |
query |
string |
Query string of the instant search. The empty string is a valid query. |
queryType |
string |
How the query should be treated by the search engine. Possible values: prefixAll, prefixLast, prefixNone |
removeWordsIfNoResults |
string |
Possible values are "lastWords" "firstWords" "allOptionnal" "none" (default) |
replaceSynonymsInHighlight |
boolean |
Should the engine replace the synonyms in the highlighted results. |
restrictSearchableAttributes |
string |
Restrict which attribute is searched. |
synonyms |
boolean |
Enable the synonyms |
tagFilters |
string |
Contains the tag filters in the raw format of the Algolia API. Setting this parameter is not compatible with the of the add/remove/toggle methods of the tag api. |
typoTolerance |
string |
How the typo tolerance behave in the search engine. Possible values: true, false, min, strict |
Here is an example of a result object you get with the result
event.
{
"hitsPerPage": 10,
"processingTimeMS": 2,
"facets": [
{
"name": "type",
"data": {
"HardGood": 6627,
"BlackTie": 550,
"Music": 665,
"Software": 131,
"Game": 456,
"Movie": 1571
},
"exhaustive": false
},
{
"exhaustive": false,
"data": {
"Free shipping": 5507
},
"name": "shipping"
}
],
"hits": [
{
"thumbnailImage": "http://img.bbystatic.com/BestBuy_US/images/products/1688/1688832_54x108_s.gif",
"_highlightResult": {
"shortDescription": {
"matchLevel": "none",
"value": "Safeguard your PC, Mac, Android and iOS devices with comprehensive Internet protection",
"matchedWords": []
},
"category": {
"matchLevel": "none",
"value": "Computer Security Software",
"matchedWords": []
},
"manufacturer": {
"matchedWords": [],
"value": "Webroot",
"matchLevel": "none"
},
"name": {
"value": "Webroot SecureAnywhere Internet Security (3-Device) (1-Year Subscription) - Mac/Windows",
"matchedWords": [],
"matchLevel": "none"
}
},
"image": "http://img.bbystatic.com/BestBuy_US/images/products/1688/1688832_105x210_sc.jpg",
"shipping": "Free shipping",
"bestSellingRank": 4,
"shortDescription": "Safeguard your PC, Mac, Android and iOS devices with comprehensive Internet protection",
"url": "http://www.bestbuy.com/site/webroot-secureanywhere-internet-security-3-devi…d=1219060687969&skuId=1688832&cmp=RMX&ky=2d3GfEmNIzjA0vkzveHdZEBgpPCyMnLTJ",
"name": "Webroot SecureAnywhere Internet Security (3-Device) (1-Year Subscription) - Mac/Windows",
"category": "Computer Security Software",
"salePrice_range": "1 - 50",
"objectID": "1688832",
"type": "Software",
"customerReviewCount": 5980,
"salePrice": 49.99,
"manufacturer": "Webroot"
},
....
],
"nbHits": 10000,
"disjunctiveFacets": [
{
"exhaustive": false,
"data": {
"5": 183,
"12": 112,
"7": 149,
...
},
"name": "customerReviewCount",
"stats": {
"max": 7461,
"avg": 157.939,
"min": 1
}
},
{
"data": {
"Printer Ink": 142,
"Wireless Speakers": 60,
"Point & Shoot Cameras": 48,
...
},
"name": "category",
"exhaustive": false
},
{
"exhaustive": false,
"data": {
"> 5000": 2,
"1 - 50": 6524,
"501 - 2000": 566,
"201 - 500": 1501,
"101 - 200": 1360,
"2001 - 5000": 47
},
"name": "salePrice_range"
},
{
"data": {
"Dynex™": 202,
"Insignia™": 230,
"PNY": 72,
...
},
"name": "manufacturer",
"exhaustive": false
}
],
"query": "",
"nbPages": 100,
"page": 0,
"index": "bestbuy"
}
FAQs
Helper for implementing advanced search features with algolia
We found that algoliasearch-helper demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 5 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
The Socket research team breaks down a sampling of malicious packages that download and execute files, among other suspicious behaviors, targeting the popular Discord platform.
Security News
Socket CEO Feross Aboukhadijeh joins a16z partners to discuss how modern, sophisticated supply chain attacks require AI-driven defenses and explore the challenges and solutions in leveraging AI for threat detection early in the development life cycle.
Security News
NIST's new AI Risk Management Framework aims to enhance the security and reliability of generative AI systems and address the unique challenges of malicious AI exploits.