Safe Haskell | None |
---|---|
Language | Haskell2010 |
Network.Algolia.Search
Description
Algolia is not based on traditional search solutions like Lucene or Solr. Algolia was built from the ground up specifically for searching through semi-structured data to power user-facing search.
Speed In order to provide the best user experience, we focus on performance - milliseconds matter, and we developed an engine capable of delivering results in a few milliseconds, fast enough to power a seamless, “as-you-type” experience - the de facto consumer-grade search experience.
Our ability to achieve unparalleled speed relies on a multitude of factors, many of which are outlined in this blog post. For instance, the Algolia engine handles the vast majority of computation at indexing time, as opposed to at query time. Beyond this, we control the full stack end-to-end. We’ve obsessed over every detail, from obtaining high quality infrastructure (bare-metal servers!) to crafting our own Ubuntu-based OS painstakingly modified for search engine performance.
Beyond speed, we focus on providing all the features necessary to build a full-fledged search experience out-of-the-box: prefix search, typo-tolerance, faceting, highlighting, and more.
Relevance
Performance is important; however, in order for search to be successful, results need to be relevant to the user. Varying from the traditional TF-IDF approach to relevancy, we built a modern tie-breaking algorithm tuned specifically for semi-structured data. Rather than calculating one “score” per result and sorting based solely off a magic number, Algolia calculates N scores and then applies N successive sorting. In layman’s terms, this means “buckets” of results are sorted by a cascade of varying criteria. When matches occur in the first criterion, the second criterion is considered to help break the tie, and so on in succession. This approach is meant to mimic how our brains naturally search for information - and as a consequence, is far easier to debug.
The Algolia engine provides various criteria for building stellar textual relevancy. On top of these, additional rules can be set to further hone the relevancy for a specific dataset. For example, a numeric “popularity” attribute could be leveraged as a potential tie-breaker rule to help more popular items rank higher. By enabling business relevance metrics to be added at will and via API, this forms the foundation for handling advanced search experiences like personalization, merchandising and more.
- mkAlgoliaClient :: ApiKey -> ApplicationId -> AlgoliaClient
- data AlgoliaClient
- newtype ApiKey = ApiKey {}
- newtype ApplicationId = ApplicationId {}
- simpleAlgolia :: (MonadIO m, Has AlgoliaClient c) => c -> ReaderT c m a -> m a
- algoliaFromEnv :: MonadIO m => ReaderT AlgoliaClient m a -> m a
- withApiKey :: MonadReader AlgoliaClient m => ApiKey -> m a -> m a
- type Result a = forall c m. (Has AlgoliaClient c, MonadReader c m, MonadThrow m, MonadIO m) => m a
- class Reconstrain f where
- newtype IndexName a = IndexName {}
- newtype ObjectId a = ObjectId {}
- newtype TaskId = TaskId {
- fromTaskId :: Int
- data IndexInfo = IndexInfo {}
- data ListIndicesResponse = ListIndicesResponse {}
- listIndices :: Maybe Int -> Result ListIndicesResponse
- data SearchParameters = SearchParameters {
- query :: Text
- attributesToRetrieve :: [Text]
- facets :: [Text]
- maxValuesPerFacet :: Maybe Int
- attributesToHighlight :: [Text]
- attributesToSnippet :: [Text]
- highlightPreTag :: Text
- highlightPostTag :: Text
- snippetEllipsisText :: Maybe Text
- restrictHighlightAndSnippetArrays :: Bool
- page :: Int
- hitsPerPage :: Int
- offset :: Maybe Int
- length :: Maybe Int
- minWordSizeFor1Typo :: Int
- minWordSizeFor2Typos :: Int
- analytics :: Bool
- analyticsTags :: [Text]
- synonyms :: Bool
- replaceSynonymsInHighlight :: Bool
- minProximity :: Int
- maxFacetHits :: Int
- percentileComputation :: Bool
- defaultQuery :: SearchParameters
- data SearchResult a = SearchResult {}
- generateSecuredApiKey :: ApiKey -> Query -> Maybe ByteString -> ByteString
- data FacetStat = FacetStat {}
- data SearchResults a = SearchResults {
- searchResultsHits :: [SearchResult a]
- searchResultsPage :: Int
- searchResultsNbHits :: Int
- searchResultsNbPages :: Int
- searchResultsHitsPerPage :: Int
- searchResultsProcessingtimeMs :: Int
- searchResultsQuery :: Text
- searchResultsParsedQuery :: Maybe Text
- searchResultsParams :: Text
- searchResultsExhaustiveNbHits :: Bool
- searchResultsQueryAfterRemoval :: Maybe Text
- searchResultsMessage :: Maybe Text
- searchResultsAroundLatLng :: Maybe Text
- searchResultsAutomaticRadius :: Maybe Text
- searchResultsServerUsed :: Maybe Text
- searchResultsFacets :: Maybe (HashMap FacetName Int)
- searchResultsFacetsStats :: Maybe (HashMap FacetName FacetStat)
- searchResultsExhaustiveFacetCount :: Maybe Bool
- searchIndex :: FromJSON a => IndexName a -> SearchParameters -> Result (SearchResults a)
- data MultiIndexSearchStrategy
- searchMultipleIndices :: [(IndexName Object, Query)] -> Maybe MultiIndexSearchStrategy -> Result [SearchResults Object]
- data DeleteIndexResponse = DeleteIndexResponse {}
- deleteIndex :: IndexName a -> Result DeleteIndexResponse
- clearIndex :: IndexName a -> Result IndexOperationResponse
- data AddObjectWithoutIdResponse a = AddObjectWithoutIdResponse {}
- addObjectWithoutId :: ToJSON a => IndexName a -> a -> Result (AddObjectWithoutIdResponse a)
- data AddObjectByIdResponse a = AddObjectByIdResponse {}
- addObjectById :: ToJSON a => IndexName a -> ObjectId a -> a -> Result (AddObjectByIdResponse a)
- data UpdateOp
- data ObjectResponse = ObjectResponse
- partiallyUpdateObject :: IndexName a -> HashMap Text UpdateOp -> Result ObjectResponse
- data RetrieveObjectResponse a = RetrieveObjectResponse {}
- retrieveObject :: FromJSON a => IndexName a -> ObjectId a -> [Text] -> Result (Maybe (RetrieveObjectResponse a))
- retrieveObjects :: [(IndexName Object, ObjectId Object, [Text])] -> Result [Object]
- data DeleteObjectResponse = DeleteObjectResponse {}
- deleteObject :: IndexName a -> ObjectId a -> Result DeleteObjectResponse
- data BatchOp a
- = AddObjectOp a
- | UpdateObjectOp (ObjectId a) a
- | PartialUpdateObjectOp (ObjectId a) (HashMap Text UpdateOp)
- | PartialUpdateObjectNoCreateOp (ObjectId a) (HashMap Text UpdateOp)
- | DeleteObjectOp (ObjectId a)
- | DeleteIndexOp
- | ClearIndexOp
- data BatchResponse = BatchResponse {}
- batch :: ToJSON a => IndexName a -> [BatchOp a] -> Result BatchResponse
- data BatchMultipleIndicesResponse = BatchMultipleIndicesResponse {}
- batchMultipleIndices :: [(IndexName Object, BatchOp Object)] -> Result BatchMultipleIndicesResponse
- data BrowseIndexResponse a = BrowseIndexResponse {
- browseIndexResponseCursor :: Maybe (Cursor a)
- browseIndexResponseHits :: !(Vector (RetrieveObjectResponse a))
- browseIndexResponsePage :: !Int
- browseIndexResponseNumberOfHits :: !Int
- browseIndexResponseNumberOfPages :: !Int
- browseIndexResponseHitsPerPage :: !Int
- browseIndexResponseProcessingTimeMs :: !Int
- browseIndexResponseQuery :: !Text
- browseIndexResponseParams :: !Text
- browseAllIndexContent :: FromJSON a => IndexName a -> Result (BrowseIndexResponse a)
- data IndexOperation
- data IndexOperationResponse = IndexOperationResponse {}
- copyOrMoveIndex :: IndexOperation -> IndexName a -> IndexName a -> Result IndexOperationResponse
- data TaskStatus
- data TaskStatusResult = TaskStatusResult {}
- waitTask :: IndexName a -> TaskId -> Result ()
- getTaskStatus :: IndexName a -> TaskId -> Result TaskStatusResult
- newtype FacetName = FacetName {}
- newtype FacetQuery = FacetQuery {}
- data FacetHit = FacetHit {}
- newtype FacetHits = FacetHits {}
- searchFacetValues :: IndexName a -> FacetName -> FacetQuery -> Result FacetHits
- newtype SynonymId = SynonymId {}
- data Synonym
- data Correction = Correction {}
- data SynonymType
- data SynonymSearch = SynonymSearch {}
- data SynonymSearchResponse = SynonymSearchResponse Object
- searchSynonyms :: IndexName a -> SynonymSearch -> Result SynonymSearchResponse
- data LogType
- data LogsResponse = LogsResponse {}
- getLogs :: Maybe Int -> Maybe Int -> Maybe (IndexName a) -> Maybe LogType -> Result LogsResponse
- data AlgoliaError
Documentation
mkAlgoliaClient :: ApiKey -> ApplicationId -> AlgoliaClient Source #
Make an algolia client from the provided API key and application id.
data AlgoliaClient Source #
Constructors
ApiKey | |
Fields |
newtype ApplicationId Source #
Constructors
ApplicationId | |
Fields |
simpleAlgolia :: (MonadIO m, Has AlgoliaClient c) => c -> ReaderT c m a -> m a Source #
Given a data type c
that implements Has AlgoliaClient c
, perform an algolia request.
algoliaFromEnv :: MonadIO m => ReaderT AlgoliaClient m a -> m a Source #
Create an algolia client from ALGOLIA_APP_ID
and ALGOLIA_KEY
environment variables.
withApiKey :: MonadReader AlgoliaClient m => ApiKey -> m a -> m a Source #
type Result a = forall c m. (Has AlgoliaClient c, MonadReader c m, MonadThrow m, MonadIO m) => m a Source #
class Reconstrain f where Source #
Convert a coercible type f
Methods
reconstrain :: f a -> f b Source #
reconstrain :: Coercible (f a) (f b) => f a -> f b Source #
Instances
Constructors
IndexName | |
Fields |
Instances
Constructors
ObjectId | |
Fields |
Constructors
TaskId | |
Fields
|
Constructors
IndexInfo | |
data ListIndicesResponse Source #
Constructors
ListIndicesResponse | |
Fields |
Arguments
:: Maybe Int | Requested page (zero-based). When specified, will retrieve a specific page; the page size is implicitly set to 100. When |
-> Result ListIndicesResponse |
List existing indexes.
data SearchParameters Source #
Constructors
SearchParameters | |
Fields
|
Instances
data SearchResult a Source #
Constructors
SearchResult | |
Instances
Show a => Show (SearchResult a) Source # | |
FromJSON a => FromJSON (SearchResult a) Source # | |
generateSecuredApiKey :: ApiKey -> Query -> Maybe ByteString -> ByteString Source #
You may have a single index containing per-user data. In that case, you may wish to restrict access to the records of one particular user. Typically, all your records would be tagged with their associated user_id, and you would add a filter at query time like filters=user_id:${requested_id} to retrieve only what the querying user has access to.
Adding that filter directly from the frontend (browser or mobile application) will result in a security breach, because the user would be able to modify the filters you’ve set, e.g. by modifying the JavaScript code.
In order to keep sending the query from the browser (which is recommended for optimal latency) but only target secured records, you can generate secured API keys from your backend and use them in your frontend code. The backend will then automatically enforce the security filters contained in the key; the user will not be able to alter them.
A secured API key is used like any other API key via the X-Algolia-API-Key request header.
Generate a secured API key Secured API keys are generated by hashing (HMAC SHA-256) the following criteria together:
a private API key (can be any API Key that is not the admin API Key), used as the secret for HMAC SHA-256;
a URL-encoded list of query parameters defining the security filters.
The result of the hashing is concatenated to the URL-encoded query parameters, and this content is encoded in Base64 to generate the final secured API key.
Constructors
FacetStat | |
Fields |
data SearchResults a Source #
Constructors
Instances
Show a => Show (SearchResults a) Source # | |
FromJSON a => FromJSON (SearchResults a) Source # | |
searchIndex :: FromJSON a => IndexName a -> SearchParameters -> Result (SearchResults a) Source #
Return objects that match the query.
You can find the list of parameters that you can use in the POST body in the Search Parameters section.
Alternatively, parameters may be specified as a URL-encoded query string inside the params attribute.
data MultiIndexSearchStrategy Source #
Constructors
None | |
StopIfEnoughMatches |
searchMultipleIndices :: [(IndexName Object, Query)] -> Maybe MultiIndexSearchStrategy -> Result [SearchResults Object] Source #
deleteIndex :: IndexName a -> Result DeleteIndexResponse Source #
Delete an existing index.
clearIndex :: IndexName a -> Result IndexOperationResponse Source #
Delete an index’s content, but leave settings and index-specific API keys untouched.
addObjectWithoutId :: ToJSON a => IndexName a -> a -> Result (AddObjectWithoutIdResponse a) Source #
Add an object to the index, automatically assigning it an object ID.
addObjectById :: ToJSON a => IndexName a -> ObjectId a -> a -> Result (AddObjectByIdResponse a) Source #
Add or replace an object with a given object ID. If the object does not exist, it will be created. If it already exists, it will be replaced.
Be careful: when an object already exists for the specified object ID, the whole object is replaced: existing attributes that are not replaced are deleted.
If you want to update only part of an object, use a partial update instead.
Constructors
Increment Scientific | |
Decrement Scientific | |
Add (Either Scientific Text) | |
Remove (Either Scientific Text) | |
AddUnique (Either Scientific Text) |
data ObjectResponse Source #
Constructors
ObjectResponse |
partiallyUpdateObject :: IndexName a -> HashMap Text UpdateOp -> Result ObjectResponse Source #
data RetrieveObjectResponse a Source #
Constructors
RetrieveObjectResponse | |
Fields |
Instances
Eq a => Eq (RetrieveObjectResponse a) Source # | |
Show a => Show (RetrieveObjectResponse a) Source # | |
FromJSON a => FromJSON (RetrieveObjectResponse a) Source # | |
Arguments
:: FromJSON a | |
=> IndexName a | |
-> ObjectId a | |
-> [Text] | Attributes to retrieve. An empty list denotes retriving all attributes.
Note that the FromJSON instance might not succeed if you exclude attributes, so
it might be necessary to use |
-> Result (Maybe (RetrieveObjectResponse a)) |
deleteObject :: IndexName a -> ObjectId a -> Result DeleteObjectResponse Source #
Constructors
data BatchMultipleIndicesResponse Source #
Constructors
BatchMultipleIndicesResponse | |
batchMultipleIndices :: [(IndexName Object, BatchOp Object)] -> Result BatchMultipleIndicesResponse Source #
data BrowseIndexResponse a Source #
Constructors
Instances
FromJSON a => FromJSON (BrowseIndexResponse a) Source # | |
browseAllIndexContent :: FromJSON a => IndexName a -> Result (BrowseIndexResponse a) Source #
data IndexOperation Source #
Instances
data IndexOperationResponse Source #
Constructors
IndexOperationResponse | |
copyOrMoveIndex :: IndexOperation -> IndexName a -> IndexName a -> Result IndexOperationResponse Source #
getTaskStatus :: IndexName a -> TaskId -> Result TaskStatusResult Source #
Get the status of a task. This can be used to wait for a task to be processed via polling.
See waitTask
for an implementation of this behavior.
Constructors
FacetName | |
Fields |
Constructors
FacetHit | |
Fields
|
searchFacetValues :: IndexName a -> FacetName -> FacetQuery -> Result FacetHits Source #
Constructors
SynonymId | |
Fields |
data Correction Source #
Constructors
Correction | |
Fields
|
data SynonymType Source #
Constructors
SynonymTy | Multi-way synonyms (a.k.a. “regular synonyms”). A set of words or phrases that are all substitutable to one another. Any query containing one of them can match records containing any of them. |
OneWaySynonymTy | One-way synonym. Alternative matches for a given input. If the input appears inside a query, it will match records containing any of the defined synonyms. The opposite is not true: if a synonym appears in a query, it will not match records containing the input, nor the other synonyms. |
AltCorrection1Ty | Alternative corrections. Same as a one-way synonym, except that when matched, they will count as 1 (respectively 2) typos in the ranking formula. |
AltCorrection2Ty | |
PlaceholderTy | A placeholder is a special text token that is placed inside records and can match many inputs. For more information on synonyms, please read our Synonyms guide. https://www.algolia.com/doc/guides/textual-relevance/synonyms/ |
data SynonymSearch Source #
Constructors
SynonymSearch | |
Fields
|
Instances
searchSynonyms :: IndexName a -> SynonymSearch -> Result SynonymSearchResponse Source #
Search or browse all synonyms, optionally filtering them by type.
data AlgoliaError Source #
Constructors
JsonParseError String | The response was a JSON value, but the library does not know how to handle it properly. |
NonConformingResult Request (Response ()) Value String | The response was not JSON. |
ToJsonInstanceMustProduceAnObject | A JSON object was expected as the response, but it was some other JSON type. |
Instances