How to order ngrx entity collection - ngrx

I have a response from backend like this:
[{ id: 4, name: 'Andrew'},
{id: 3, name: 'Rebecca'},
{id: 2, name: 'Joseph'},
{id: 1, name: 'Kristin'}]
The order is by descending id. From the last one to first one.
I have an entityAdapter defined in this way:
export const folderAdapter: EntityAdapter<Person> = createEntityAdapter<Person>({
selectId: person => person.id,
sortComparer: false,
});
into the reducer I created this function:
on(PeopleActions.loadAllPeople, (state, action): PeopleState => {
return {
...state,
people: adapter.addMany(action.people, state),
};
}),
when I go to see my state I have this situation:
ids:[4,3,2,1],
entities: {1: {id: 1, name: 'Kristin'}, 2: {id: 2, name: 'Joseph'}, 3: {id: 3, name: 'Rebecca'}, 4: { id: 4, name: 'Andrew'}}
}
This also happen into the ngFor. I tried to set return value to zero in ngfor keyvalue but nothing change. How can I change the order in entities? is there a particular property?

The EntityAdapter has the parameter sortComparer for this exact purpose.
All you need it to instead of using
sortComparer: false
you give it the function you would like to have sorting your entity ids
sortComparer: (a ,b) => a.id - b.id
As per ngrx's docs:
If provided, the state.ids array will be kept in sorted order based on comparisons of the entity objects, so that mapping over the IDs array to retrieve entities by ID should result in a sorted array of entities.
If not provided, the state.ids array will not be sorted, and no guarantees are made about the ordering. In other words, state.ids can be expected to behave like a standard Javascript array.

Related

Cloud Firestore : Query nested map of arrays

My firestore document structure looks like this
doc1
{
name: 'Test',
categories: [
{
allNames: ['name1', 'name2', 'name3],
id: 'abcd'
},
{
allNames: ['name4', 'name5'],
id: 'xyz'
},
]
doc2
{
name: 'Test2',
categories: [
{
allNames: ['name7'],
id: 'abcd3'
},
{
allNames: ['name4', 'name5'],
id: 'xyz'
},
]
I am using the JS SDK and wanted to query all document with a certain category(id or name). So if I query with categories.id equal to xyz or categories.allNames contains name1, both the above documents should be returned.
Are both these queries possible or do I need to remodel my data ?
Thank you !
You cannot query arrays that way. If you know the exact object then you could use array-contains as shown below:
firestore.collection('col').where('categories', 'array-contains', {id: 'abc', allNames: ['name1']})
One solution would be to store another array which contains category IDs only like this:
{
name: 'Test1',
categories: [...],
categoryIds: ['abcd', 'xyz']
}
Now you can use arrayContains even if you know the category ID only and not the whole object in categories array. The same method can be used for allNames.
Categories can also be made a sub-collection where each object in categories array would be a document. Then you can use Collection Group queries to find category documents with that ID or allNames and find parent document ID using the DocumentReference.

DynamoDB - UpdateItem where X <= Y

I have a DynamoDb table defined with a composite key of
$response = $this->dynamoDb->createTable([
...
'KeySchema' => [
[
'AttributeName' => 'product_code',
'KeyType' => 'HASH'
],
[
'AttributeName' => 'token',
'KeyType' => 'RANGE'
]
]
...
]);
I want to be able to update all records where "product_code" = "X" and "created_at" <= "Y". I assume it must be possible but I am a bit stumped. The updateItem method requires the full key but I want a conditional update without specifying a key. My latest stub reads as
$response = $this->dynamoDb->updateItem([
'TableName' => 'products',
'ExpressionAttributeValues' => [
':val1' => ['N' => (string)$this->input['product_code']]
':val2' => ['N' => (string)$this->product['created_at']['N']],
':val3' => ['N' => (string)strtotime("now")],
],
'ConditionExpression' => 'product_code = :val1 AND processed_at <= :val2',
'UpdateExpression' => 'set processed_at = :val3'
]);
But the generated error message reads as follows:
[Key] is missing and is a required parameter
Which command should I be using? Any help building my query is greatly appreciated.
The following is taken from AWS DynamoDB API reference for UpdateItem:
For the primary key, you must provide all of the attributes. For example, with a simple primary key, you only need to provide a value for the partition key. For a composite primary key, you must provide values for both the partition key and the sort key.
In your code (the update item part) you provide only hash key (product_code). You have to provide the range key (token) as well in your ConditionExpression property, because you defined a composite key.
EDIT:
(regarding the comment)
The following describes the parameters for UpdateItem:
Request Parameters
...
Key
The primary key of the item to be updated. Each element consists of an
attribute name and a value for that attribute.
For the primary key, you must provide all of the attributes. For
example, with a simple primary key, you only need to provide a value
for the partition key. For a composite primary key, you must provide
values for both the partition key and the sort key.
Type: String to AttributeValue object map
Required: Yes
...
As you can see, the primary key is required for an UpdateItem operation.
So you cannot use a secondary index to point UpdateItem to a collection of items to update.
However, you can query the table by a secondary index, and collect the primary keys of the resulted items, say in an array keysToUpdate.
Then you can update the desired items, whose keys are in keyToUpdate.

FOSElasticaBundle sort not working

The configuration of my elastica type looks like following:
acme_article:
mappings:
title: {type:string, index_analyzer:acme_analyzer}
content: {type:string, index_analyzer:acme_analyzer}
slug: ~
media: {type:string, index_analyzer:acme_analyzer}
categories:
type: "object"
properties:
name: ~
id: ~
instance:
type: "object"
properties:
name: ~
created_by: ~
created_at: ~
I have Repository class which extends FOS\ElasticaBundle\Repository and everything works well except sorting.
$query = new \Elastica\Query();
$query->setSort(array('created_at' => array('order' => 'desc')));
return $this->find($query);
Getting some irelevant result, totally without order. Then, I tried to add model id in index and try to sort by id but also without success.
Solution is to set {type:date} on created_at field. In that case ES sorting by timestamp and everything is ok.
Sorting by id is not working because in some way categories.id override main id and then I got results ordered by category.id instead entity id.

Self joins in Batmanjs

How can I implement the self-joins in Batmanjs?
In rails, as found here, it goes like this:
class Employee < ActiveRecord::Base
has_many :subordinates, class_name: "Employee", foreign_key: "manager_id"
belongs_to :manager, class_name: "Employee"
end
My current Batmanjs equivalent model looks like this:
class Employee extends Batman.Model
#resourceName: 'employees'
#storageKey: 'employees'
#persist Batman.LocalStorage
#has_many 'subordinates', name: "Employees", foreignKey: "manager_id"
#belongs_to 'manager', name: "Employee"
I think that should work, if you just switch:
has_many/belongs_to => hasMany/belongsTo
name: "Employees" => name: "Employee".
Also, you may have to add an encoder for id with the LocalStorage adapter. LocalStorage converts the value to a string, but batman.js expects an integer, so you have to coerce it back to integer in the encoder.
Here's an example of self-joins (you can copy-paste the encoder from there, too):
http://jsbin.com/cukapedo/18/edit
Pasted here for posterity:
class App.Color extends Batman.Model
#resourceName: 'color'
#persist Batman.LocalStorage
#encode 'name', 'source_color_id'
# required for numbers in localStorage:
#encode 'id',
encode: (val) -> +val
decode: (val) -> +val
#hasMany 'child_colors', name: 'Color', foreignKey: 'source_color_id'
#belongsTo 'source_color', name: 'Color'

Define Multiple-Columns as PK in YDN-DB

When define a schema with ydn-db I can define a single column as PK with this code:
var products = {
name: 'products',
keyPath: 'id_product',
autoIncrement: true,
indexes: [
{keyPath: 'id_product'},
{keyPath: 'id_supplier'}
]
};
var schema = {
stores: [products]
};
How I can define a Store (table) with one PK with two columns or more? Thanks
How I can define a Store (table) with one PK with two columns or more?
I am not sure answering your question. IndexedDB (ynd-db is very IDB centric) can have only one PK. But primary key can be compound key compose of multiple keyPath (column) using array keypath. It is define like this
var products = {
name: 'products',
keyPath: ['id_category', id_product']
};

Resources