Match a specific keyword to a specific result - algolia

We have a need to make a specific search keyword offer a specific result. Is there a way to do this from within the Algolia console?

There isn't such feature out-of-the box but what you can reproduce such behavior using 2 different solutions:
Quick work-around: adding the search keywords in your records
You could add a new keyword attribute to your objects and list there all the keywords you want to use for every single object.
with attributesToIndex:
Putting that keyword attribute on top of your attributesToIndex will make it match before the other attributes.
or with attributesForFaceting:
Putting that keyword attribute in the attributesForFaceting will let you filter on it. For every single search, you could do an extra query putting the query string as the filter: index.search('' /* empty query string: match all */, { facetFilters: "keyword:THE_USER_QUERY_STRING" }) and check use the results if there is a match, otherwise use the regular search query.
Better option: using an additional index
Using an additional index, you would push 1 record per search keyword you want to handle.
A record of such index would look like this:
{
"keyword": "mykeyword",
"object": {
// the object you want to retrieve
}
}
Configure your attributesToIndex with keyword only. You may also want to configure the queryType of that extra index to prefixNone so the native prefix search doesn't trigger. (instead, you could also use the facetFilters approach here).
For every single search, you would then query 2 indices: your original index and this extra index. In case the extra one has a match, you can inject the object in your search results.

Related

Firestore: Where query (==) on map field

I have a collection with shipments in them.
I want to filter on postalcode which is a part of the 'address_from' map.
Is this possible and are there extra steps required, indexes for example, to make this work?
query.where('address_from.postalcode', '==', shipment_code);
That query should just work. Any single field query should work without creating an index, as all fields are indexed by default. Queries that require an index will yield and error message telling you that one needs to be created, and provide a link to the console to automatically do that.

Algolia: Filter Index by string array attribute with a string array of possible values

I have an Algolia Index that contains objects like this:
id: 2,
name: test,
important: ["lorem", "ipsum", "dolor", "sit", "amet"]
I want to retrieve all entries that e.g. contain either "dolor" or "sit".
How would I go about this?
Note: This is just an example, the importantarray of each entry would normally contain around 1 to 4 values (in total around 1.000 possible values). The array to filter it by / to search for could have anywhere between 1 to 400 values.
What AFAIK doesn't work:
searching in Facet Values by using a facetQuery: facetQuery does not allow for boolean operators. Therefore I can only search for only one of "dolor" or "sit" at once, see docs.
The filters docs however says
Non-numeric attributes (e.g. strings) need to be set up as categories, which we call facets.
So I am wondering if this is possible at all...? Or maybe I am approaching this issue the wrong way?
You are looking at the right place and need to combine attributesForFaceting and filters:
set the important attribute as an attributesForFaceting either via API or the Dashboard
then use the filters to filter on your desired values
Your filter will look like this: { "filters": "important:dolor OR important:sit" }

How do I make Algolia Search guaruntee that it will return a number of results

I need Algolia to always return me 5 results from a full text search even if the query text itself bears little or no relevance to the actual returned results. Before someone suggests it, I have already tried to set the removeWordsIfNoResults option to all of it's possible modes and this still doesn't guarantee that I get my 5 results.
The purpose of this is to create a 'relevant entities' sidebar where the name of the current entity is used to search for other entities.
Any suggestions?
Using the removeWordsIfNoResults=allOptional query parameter is indeed a good way to go -> because all query words are required to match an object by default, fallbacking to "optional" is a good way to still retrieve results if one you the query words (or the combination of words) doesn't match anything.
index.search(query, { removeWordsIfNoResults: 'allOptional' });
Another solution is to always consider all query words as optional (not only as a fallback); to make sure the query foo bar baz is interpreted as OPT(foo) AND OPT(bar) AND OPT(baz) <=> foo OR bar OR baz. The difference is that this query will retrieve more results than the previous one because 1 single matching word will be enough to retrieve the object.
index.search(query, { optionalWords: query });
That being said, there is no way to force the engine to retrieve "at least" 5 results. What I would recommend is to have a small frontend logic:
- do the query with removeWordsIfNoResults or optionalWords
- if the engines returns less than 5 results, do another query

Extensive filtering

Example:
{
shortName: "KITT",
longName: "Knight Industries Two Thousand",
fromZeroToSixty: 2,
year: 1982,
manufacturer: "Pontiac",
/* 25 more fields */
}
Ability to query by at least 20 fields which means that only 10 fields are left unindexed
There's 3 fields (all number) that could be used for sorting (both ways)
This leaves me wondering that how does sites with lots of searchable fields do it: e.g real estate or car sale sites where you can filter by every small detail and can choose between several sort options.
How could I pull this off with MongoDB? How should I index that kind of collection?
Im aware that there are dbs specifically made for searching but there must be general rules of thumb to do this (even if less performant) in every db. Im sure not everybody uses Elasticsearch or similar.
---
Optional reading:
My reasoning is that index could be huge but the index order matters. You'll always make sure that fields that return the least results are first and most generic fields are last in index. However, what if user chooses only generic fields? Should I include non-generic fields to query anyway? How to solve ordering in both ways? Or index intersection saves the day and I should just add 20 different indexes?
text index is your friend.
Read up on it here: https://docs.mongodb.com/v3.2/core/index-text/
In short, it's a way to tell mongodb that you want full text search over a specific field, multiple fields, or all fields (yay!)
To allow text indexing of all fields, use the special symbol $**, and define it of type 'text':
db.collection.createIndex( { "$**": "text" } )
you can also configure it with Case Insensitivity or Diacritic Insensitivity, and more.
To perform text searches using the index, use the $text query helper, see: https://docs.mongodb.com/v3.2/reference/operator/query/text/#op._S_text
Update:
In order to allow user to select specific fields to search on, it's possible to use weights when creating the text-index: https://docs.mongodb.com/v3.2/core/index-text/#specify-weights
If you carefully select your fields' weights, for example using different prime numbers only, and then add the $meta text score to your results you may be able to figure out from the "textScore" which field was matched on this query, and so filter out the results that didn't get a hit from a selected search field.
Read more here: https://docs.mongodb.com/v3.2/tutorial/control-results-of-text-search/

Search and return result in array

I have a collection, like so:
post = {"topics":["japan","japanese","england","chinese"]}
post = {"topics":["canada","japan"]}
post = {"topics":["usa"]}
Now I want to implement a query can return a list of elements by checking the "topics" field to see if it contains a certain character.
For example, query for "ja", it returns all the tags start with "ja":
["japan", "japanese"],
query for "c", returns ["chinese","canada"]
You can not resolve this problem with a single query. You have to maintain either a global list or collection of all tags in order to search them efficiently using regular expressions or you need to iterate over all documents for matching the tags individually for each document.