How to filter by derived facets in algolia - algolia

Given the following indices:
{
id: 1,
distance: [4, 10]
},
{
id: 2,
distance: [1, 2]
},
{
id: 3,
distance: [9, 10]
}
After enabling faceting on distance to be able to apply numerical filters on it, I want to apply additional filtering on a derived attribute that I'll call distance_range. It derives its value through custom logic on an existing attribute for example:
// In JS:
distance_range: Math.floor(( distance - 0.5 ) / 5) * 5 + "-" + Math.ceil(( distance ) / 5) * 5
Which would transform each distance number into a range "0-5", "5-10", etc.
{
id: 1,
distance: [4, 10],
distance_range: ["0-5", "5-10"]
},
{
id: 2,
distance: [1, 2]
distance_range: ["0-5"]
},
{
id: 3,
distance: [9, 10]
distance_range: ["5-10"]
}
What is the best way to arrive at such an index? Do I have the process the data beforehand, or does algolia have such a feature to transform attributes on the fly?

Algolia uses a custom data structure to index your data in order to deliver results as fast as possible.
Rebuilding an index in real-time would be too long to get an answer, which is why, even for sorting, Algolia requires you to duplicate your data into multiple indices.
If you only had to compute the new attribute for display, it would definitely be achievable with front-end logic, both autocomplete.js and instantsearch.js have a method to transform the data before displaying it.
However, since you want to filter on it, Algolia needs this information in the data structure, so you'll have to do this computation beforehand.
Also, don't forget to add this new attribute to attributesForFaceting.

Related

How to do multiple where query without effect data in TypeORM?

I want to do multiple where query without effect data. I want to get data that include at least 1 data per array. Pseudo code
data =[1,3]
array1 = [1,2]
array2 = [3,4]
if(data.IsIntersect(array1) and data.IsIntersect(array2))
IsIntersect checks are there a intersection beetween arrays
I did so far
queryBuilder.andWhere(
'properties.id IN (:...sizeIds) AND properties.id IN (:...colorIds)',
{ sizeIds: [1, 2], colorIds: [3, 4] },
);
It returns empty because firstly checks properties for 'sizeIds' then it checks for 'colorIds'. For example
properties includes 1,3
check for sizeIds, returns 1
check for colorIds, return empty
How can I do that with typeORM?
How can properties.id be 1 and 3? And if it is, how could 1 or 3 be in both? You're asking for the impossible.
I assume you mean to ask for when properties.id is 1 or 3, because if it is [1,3] then you should use the postgres array syntax {1,3} & the ANY keyword (some variation on this: Check if value exists in Postgres array).
tldr, I think all you need is brackets and OR instead of AND:
queryBuilder.andWhere(
'(properties.id IN (:...sizeIds) OR properties.id IN (:...colorIds))',
{ sizeIds: [1, 2], colorIds: [3, 4] },
);
If properties.id is in fact an array, then please add the entity definition to your question. If you want to merge the rows where properties.id is in the list you will need a GROUP BY (https://orkhan.gitbook.io/typeorm/docs/select-query-builder).

Update an element in an array which is within an array in mongodb

Schema
{
_id: 'Unique_id',
array_key: [{
'm1': [7, 5, 6, 6, 1, 2, 3]
},
{
'm2': [1, 5, 3, 7, 9, 2, 3]
},
]
}
I want to update any element in array_keys m1 field's array.
{'m1': [7,5,6,6,1,2,3]}
E.g. I want to update 6 at index 3 in that array.
I found this in MongoDB's official documentation
It seems that one is allowed to add value at specific position but not update it (going by that documentation).
~p.s Later I'd try to implement this using mongoose
Update : The array_key in the schema will hold daily work hour for an employee which will be represented in months format on the frontend. m1 and m2 are used in that respect.

Swift: Set<Object> fundamental operations result in copies or pointers?

I'm currently looking for some reference, outside apple's swift programming reference for the memory space of Set types and resulting fundamental operations (union, intersection, exclusion, subtraction etc)
Given the below pseudo code:
var entities = Set<GKEntity>()
var subSetA = Set<GKEntity>()
var subSetB = Set<GKEntity>()
Each subset will have a subclass of GKEntity which will be called on some routines I will use elswhere in my application.
When I use the union of these subsets, IE: I will have set as the superset of all subsets, or the union of all subsets.
Does this mean that the superset will be a copy of the elements in the subset or will they be pointers only?
I ask this for memory space usage as if the operation requires copying or allocating new memory adresses, I will need to use a different strategy of storing my elements.
From a purely structural standpoint, I assume these will be "shallow" copies meaning they will be pointers to memory adresses, but once I have created the superset as the union of all subsets, I want any removal or addition to be reflected on the superset, or down on the particular subset if the operation is made on the superset.
Hope this question is valid
Note, I'm assuming you mean this GKEntity.
Since GKEntity is a class, the sets you created will store references (pointers) to those actual GKEntity objects. So any changes to the objects in a subset will be reflected in the superset.
Here is a short piece of code that demonstrates this:
class A: IntegerLiteralConvertible, Hashable, CustomStringConvertible {
var x: Int
required init(integerLiteral value: Int) {
self.x = value
}
var hashValue: Int {
return x
}
var description: String {
return String(x)
}
}
func ==(lhs: A, rhs: A) -> Bool {
return lhs.hashValue == rhs.hashValue
}
let setA: Set<A> = [1, 2, 3, 4]
let setB: Set<A> = [5, 6, 7, 8]
print(setA) // [2, 3, 1, 4]
print(setB) // [5, 6, 7, 8]
let union = setA.union(setB)
print(union) // [2, 4, 5, 6, 7, 3, 1, 8]
setA.first!.x = 30
print(union) // [30, 4, 5, 6, 7, 3, 1, 8]
As you can see, I made a change (changed x from 2 to 30) to the first item in setA. Then I printed out union, which did contain a 30 in it.

How to sum arrays from different documents in MongoDB Aggregation?

I have a collection of documents, each containing an array of revenues of different lengths.
I want to get a single array of revenue from the values that match the query.
Example data
...
{"cohort": "2112", "revenue": [1, 1, 0, 0, 5], ...},
{"cohort": "2113", "revenue": [0, 0, 2, 0], ...},
{"cohort": "2114", "revenue": [0, 1, 3], ...}
...
Expected result for cohorts 2113 and 2114
[0, 1, 5] or [0, 1, 5, 0]
The two results are equal for my purpose, since I know the length of the shortest array.
Is there any way to perform the operation with MongoDB Aggregate pipeline?
Or can you suggest a better solution?
And yes, I use PyMongo to access the database.
I just discovered this new 3.2 feature: includeArrayIndex.
So you can unwind the field revenue with this option and then sum using your includeArrayIndex field as id and then sort and push to get a new array.
Reference: https://docs.mongodb.org/manual/reference/operator/aggregation/unwind/

How to add integer to array (with explicite int index) in swift?

I read swift handbook and was trying to do some exercises. But I run into a problem and I do not know if I do something wrong or if xCode 6 beta is just buggy.
// Playground - noun: a place where people can play
import Cocoa
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
var lastLargest = Integer[]()
var index = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
//lastLargest[index] = number
index++
largest = number
}
}
}
index
lastLargest
largest
As soon as I uncomment lastLargest[index] = number I do not get any results on right side in playground. Nor I get any infos about index, lastLargest or largest.
Following example does not work either:
var index2 = 0
var lastLargest2 = Integer[]()
lastLargest2[index2] = 1
index2++
lastLargest2[index2] = 2
You are appending using an out of bound array-index. Don't do that. Instead, use append:
lastLargest.append(number)
From Apple's documentation:
You can’t use subscript syntax to append a new item to the end of an array. If you try to use subscript syntax to retrieve or set a value for an index that is outside of an array’s existing bounds, you will trigger a runtime error.
When you're using explicit indexes (subscript notation) to set values in a mutable array, some value must already exist in that array at that index. When you use subscript notation, you're essentially using a 'set', rather than a 'set and add if necessary'.
As a result, you should be using:
lastLargest.insert(number, atIndex: index)
If you want to insert a new item. This will let you insert an item at the specified index, assuming your collection's size is already greater than or equal to the index you're trying to replace.