Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Algolia AND search through an array

Tags:

algolia

I am looking for a way to search in Algolia a record where at least one element of an array meets several conditions. As an example, imagine this kind of record:

{
    "name": "Shoes",
    "price": 100,
    "prices": [
    {
        "start": 20160101,
        "end": 20160131,
        "price": 50,
    },
    {
        "start": 20160201,
        "end": 20160229,
        "price": 80,
    }
    ]
}

I am looking for a way to do a query like the following:

prices.price<60 AND prices.start<=20160210 AND prices.end>=20160210

(A product where the price is less than 60 for the given date)

That query should not return anything because the price condition is not met for that date but the record is returned anyway. Probably because the condition is met "globally" among all prices.

I am a beginner with Algolia and trying to learn. Is there a way I can do the desired request or will I have to go for a separate index for prices and use multiple queries?

Thanks.

like image 933
Benoît Bouré Avatar asked Jan 08 '16 17:01

Benoît Bouré


People also ask

Can you index an array?

Elements in NumPy arrays can be accessed by indexing. Indexing is an operation that pulls out a select set of values from an array. The index of a value in an array is that value's location within the array. There is a difference between the value and where the value is stored in an array.

What is Algolia API?

The Search REST API is the core of Algolia Search. Around it, Algolia built a complete ecosystem, of libraries, tools, and a dashboard. You should use the official API clients and libraries to implement Algolia. They're all open source, and the code is available on GitHub.


1 Answers

When a facetFilter or tagFilter is applied on an array, Algolia's engine checks if any element of the array matches and then goes to the next condition.

The reason it behaves that way and not the way you expected is simple: let's assume you have an array of strings (like tags):

{ tags: ['public', 'cheap', 'funny', 'useless'] }

When a user wants to find a record that is "useless" and "funny", this user is not looking for a tag that is both "useless" and "funny" at the same time, but for a record containing both tags in the array.

The solution for this is to denormalize your object in some way: transforming a record with an array of objects to multiple records with one object each.

So you would transform

{
    "name": "Shoes",
    "price": 100,
    "prices": [
      { "start": 20160101, "end": 20160131, "price": 50 },
      { "start": 20160201, "end": 20160229, "price": 80 }
    ]
}

into

[
  {
    "name": "Shoes",
    "default_price": 100,
    "price": { "start": 20160101, "end": 20160131, "price": 50 }
  },
  {
    "name": "Shoes",
    "default_price": 100,
    "price": { "start": 20160201, "end": 20160229, "price": 80 }
  }
]

You could either do this in the same index (and use distinct to de-duplicate), or have one index per month or day. It really depends on your use-case, which makes it a bit hard to give you the right solution.

like image 71
Jerska Avatar answered Sep 22 '22 00:09

Jerska