useGetList fetched data sorted by id ignoring sort option - react-admin

The problem is that data fetched by useGetList is sorted by ids of the objects and ignores the order by other keys given by my backend. This is my call example (try to order by name):
const { data, loading } = useGetList(
'my-controller-path',
{ page: 1, perPage: 10000 },
{ field: 'name', order: 'ASC' },
{}
)
console.log(data)
When I print data after this call, data is sorted by 'id' and not by 'name'. It's not a problem with the backend because I hardcoded returning data to eliminate this from equation. Data provided from backend:
data: [
{ id: 2, name: 'Ana'},
{ id: 3, name: 'Bea'},
{ id: 1, name: 'Cena'}
]
And when I print data on console after using useGetList:
[
{id: 1, name: "Cena"},
{id: 2, name: "Ana"},
{id: 3, name: "Bea"}
]
Any idea what is causing the problem? I read the source code of useGetList and don't quite understand if the problem lays there. The link to source code.

How does your API works ? In my case, I needed to map the sort properties like so:
getList: async (
resource,
{ pagination: { page, perPage }, sort: { field, order }, filter }
) => {
const query = {
...filter,
sort: order.toLowerCase(),
order: field,
page: JSON.stringify(page),
limit: JSON.stringify(perPage),
};
...
}
in my custom data provider to match my API sort and order properties.

Related

How to find if two arrays contain any common item in SQL? With one array being my set result and the other a list of 'ids'?

This is currently what my entities look like:
Category Entity
#Entity('category')
export class Category extends BaseEntity {
#PrimaryGeneratedColumn("uuid")
id: string;
#Column({ type: 'text', unique: true })
name: string;
#Column({ type: "text", unique: true })
#Index()
slug: string;
#ManyToMany(() => Listing, (listing) => listing.categories, { cascade: true, onDelete: 'CASCADE' })
listings?: Listing[];
}
Listing Entity
#Entity('listing')
export class Listing extends BaseEntity {
#PrimaryGeneratedColumn("uuid")
id: string;
#ManyToMany(() => Category, (category) => category.listings)
#JoinTable()
categories: Category[];
}
Query 1 (what I'm currently using)
And this is currently what my query looks like:
const listings = await connection.getRepository()
.createQueryBuilder('listing')
.distinct(true)
.leftJoinAndSelect('listing.categories', 'category', 'category.slug IN (:...slugs)', {slugs: [ 'mens-shirts', 'clearance' ]})
.getMany()
Query 1 Result
[] // an empty list of Listings (Type: Listing[])
Query 2 (checking to see if the innerJoinAndSelect was working properly)
const listings = await connection.getRepository()
.createQueryBuilder('listing')
.distinct(true)
.innerJoinAndSelect('listing.categories', 'category')
.getMany();
Query 2 Result
[
Listing {
id: 'c24ea98d-da53-4f14-8706-a3597f3ee4d1',
categories: [ [Category], [Category] ]
},
Listing {
id: 'e8b3e680-85b6-4701-9ad7-bf65de348e76',
categories: [ [Category], [Category] ]
},
Listing {
id: '1bb04ea0-8435-44d6-856f-8eb53f24e941',
categories: [ [Category], [Category] ]
},
Listing {
id: '0735142d-fd38-4fad-b5a7-0356373dd0a3',
categories: [ [Category], [Category] ]
},
]
The innerJoinAndSelect method is working and giving me the results back, and I know why I'm getting an empty array when using the first query. It's because I'm trying to find the field slug on the Array of Categories, instead of each Category in the Array.
Question:
How would I search for the slug names [ 'mens-shirts', 'clearance' ], in the array of Categories (Type: Category[]), using TypeORM's QueryBuilder? Or How could I check to see if each Category in the Categories field, has a slug, that is in [ 'mens-shirts', 'clearance' ]. Is it possible?
You need to use = ANY() when searching if an element is inside an array. So change 'category.slug IN (:...slugs)' to 'category.slug = ANY(:slugs)' (notice how you don't need to use "spread" inside ANY, just reference the array directly)

How to select all documents where one date field is after another date field in FaunaDB

I have a very simple collection with documents that look like this:
{
...
latestEdit: Time(...),
lastPublished: Time(...)
}
I would like to query all documents that have a latestEdit time that's after lastPublished time.
I find FQL to be very different to SQL and I'm finding the transition quite hard.
Any help much appreciated.
Fauna's FQL is not declarative, so you have to construct the appropriate indexes and queries to help you solve problems like this.
Fauna indexes have a feature called "bindings", which allow you to provide a user-defined function that can compute a value based on document values. The binding lets us index the computed value by itself (rather than having to index on latestEdit or lastPublished). Here's what that might look like:
CreateIndex({
name: "edit_after_published",
source: {
collection: Collection("test"),
fields: {
needsPublish: Query(
Lambda(
"doc",
Let(
{
latestEdit: Select(["data", "latestEdit"], Var("doc")),
lastPublished: Select(["data", "lastPublished"], Var("doc")),
},
If(
GT(Var("latestEdit"), Var("lastPublished")),
true,
false
)
)
)
)
}
},
terms: [ { binding: "needsPublish" } ]
})
You can see that we define a binding called needsPublish. The binding uses Let to define named values for the two document fields that we want to compare, and then the If statement checks to see if the latestEdit value is greather than lastPublished value: when it is we return true, otherwise we return false. Then, the binding is used in the index's terms definition, which defines the fields that we want to be able to search on.
I created sample documents in a collection called test, like so:
> Create(Collection("test"), { data: { name: "first", latestEdit: Now(), lastPublished: TimeSubtract(Now(), 1, "day") }})
{
ref: Ref(Collection("test"), "306026106743423488"),
ts: 1628108088190000,
data: {
name: 'first',
latestEdit: Time("2021-08-04T20:14:48.121Z"),
lastPublished: Time("2021-08-03T20:14:48.121Z")
}
}
> Create(Collection("test"), { data: { name: "second", lastPublished: Now(), latestEdit: TimeSubtract(Now(), 1, "day") }})
{
ref: Ref(Collection("test"), "306026150784664064"),
ts: 1628108130150000,
data: {
name: 'second',
lastPublished: Time("2021-08-04T20:15:30.148Z"),
latestEdit: Time("2021-08-03T20:15:30.148Z")
}
}
The first document subtracts one day from lastPublished and the second document subtracts one day from latestEdit, to test both conditions of the binding.
Then we can query for all documents where needsPublish results in true:
> Map(Paginate(Match(Index("edit_after_published"), true)), Lambda("X", Get(Var("X"))))
{
data: [
{
ref: Ref(Collection("test"), "306026106743423488"),
ts: 1628108088190000,
data: {
name: 'first',
latestEdit: Time("2021-08-04T20:14:48.121Z"),
lastPublished: Time("2021-08-03T20:14:48.121Z")
}
}
]
}
And we can also query for all documents where needsPublish is false:
> Map(Paginate(Match(Index("edit_after_published"), false)), Lambda("X", Get(Var("X"))))
{
data: [
{
ref: Ref(Collection("test"), "306026150784664064"),
ts: 1628108130150000,
data: {
name: 'second',
lastPublished: Time("2021-08-04T20:15:30.148Z"),
latestEdit: Time("2021-08-03T20:15:30.148Z")
}
}
]
}

how to join collections in faunadb?

I want to get nested ref's value within the query I'm executing, but by default response is returning the ref of other collection. consider this minimum example; here are user and coin models, within "users" and "coins" collections
user { // ref: 123456
name: foo
location: bar
}
coin { // ref: 124457
amount: 5457
awardedTo: Ref(Collection("users"), "123456")
}
when I run this query
q.Get(q.Ref(q.Collection("coins"), "124457"))
the response is something like this:
{
data: {
amount: 5457,
awardedTo: #ref: {id: "123456", collection: {…}}
},
ref: #ref: {id: "124457", collection: {…}},
ts: 1622547855525255
}
But how is it possible to get nested user's value in the same query to have a response like this:
{
data: {
amount: 5457,
awardedTo: {
name: foo,
location: bar
}
},
ref: #ref: {id: "124457", collection: {…}},
ts: 1622547855525255
}
I have read Join's documentation but it wasn't helpful in this case, and also tried this way, but it didn't work either:
q.Let({
coin: q.Get(q.Ref(q.Collection("coins"), '124457'))
},
q.Union(
q.Get(q.Select(["data","awaredTo"], q.Var("coin"))),
q.Var("coins")
)
)
you can use this FQL:
Let(
{
coin: Select(['data'],Get(Ref(Collection("coin"), "1"))),
user: Select(['data'],Get(Select(['awardedTo'],Var('coin'))))
},
Merge(Var('coin'),{awardedTo:Var('user')})
)
It retrieves data from coin, extracts the user ref and merge all together.
Luigi

How to search for/select by included entity but include all related entities into result set

In my application, I am using sequelize ORM. There are several entities: A Tool can have Tags and Categories.
Now I want to search for all Tools, that have a specific Tag, but I want to include all relating Tags of that tool (not just the specific one). If I now place a where statement into the include, only specified Tags are included into the result set (see [2]). I tried to limit the Tags in the outer where statement (see [1]), but this does not help either.
Example
Tool A has Tags t1, t2 and t3. Now I want to search all Tools that have the Tag t3, but the result set shall contain all three tags.
Expected result:
Tool A
\
- Tag t1
- Tag t2
- Tag t3
db.Tool.scope('published').findAll({
where: { '$tool.tag.name$': filter.tag }, // [1] Does not work
include: [
{
model: db.User,
attributes: ['id', 'username']
},
{
model: db.Tag,
attributes: ['name'],
through: { attributes: [] },
// [2] Would limit the result specified tag
// where: {
// name: {
// [Op.and]: filter.tag
// }
// }
},
{
model: db.Category,
attributes: ['id', 'name', 'views'],
through: { attributes: ['relevance'] },
where: {
id: {
[Op.and]: filter.category
}
}
}
],
where: {
title: {
[Op.like]: `%${filter.term}%`,
}
},
attributes: ['id', 'title', 'description', 'slug', 'docLink', 'vendor', 'vendorLink', 'views', 'status', 'createdAt'],
order: [['title', 'ASC'], [db.Tag, 'name', 'ASC']]
})
I know I could perform this by performing a select via the Tag in the first place (db.Tag.findAll() instead of db.Tool.findAll(); I've already done this elsewhere in my project), but at the same time I also want to be able to filter by another entity (Category) the same way. So the Tool.findAll() should be the starting point.
Any help appreciated!
First off, you have two where clauses in your top-level query:
where: { '$tool.tag.name$': filter.tag }, // [1] Does not work
// ...
where: {
title: {
[Op.like]: `%${filter.term}%`,
}
},
I think your best approach is going to be with a literal subquery in the WHERE clause. Basically we want to find the ids of all of the tools that have the right tag and that contain the filter.term.
The subquery part for the WHERE looks something like...
SELECT ToolId FROM ToolTags WHERE TagId='t2';
Inspired by the subquery solution from this post Sequelize - subquery in where clause
// assuming your join table is named 'ToolTags' in the database--we need the real table name not the model name
const tempSQL = sequelize.dialect.QueryGenerator.selectQuery('ToolTags',{
attributes: ['ToolId'],
where: {
TagId: filter.tag
}})
.slice(0,-1); // to remove the ';' from the end of the SQL
db.Tool.scope('published').findAll({
where: {
title: {
[Op.like]: `%${filter.term}%`,
},
id: {
[Op.In]: sequelize.literal(`(${tempSQL})`)
}
},
include: [
{
model: db.User,
attributes: ['id', 'username']
},
{
model: db.Tag,
attributes: ['name'],
through: { attributes: [] },
},
// {
// model: db.Category,
// attributes: ['id', 'name', 'views'],
// through: { attributes: ['relevance'] },
// where: {
// id: {
// [Op.and]: filter.category
// }
// }
// }
],
attributes: ['id', 'title', 'description', 'slug', 'docLink', 'vendor', 'vendorLink', 'views', 'status', 'createdAt'],
order: [['title', 'ASC'], [db.Tag, 'name', 'ASC']]
})
I commented out your category join for now. I think you should try to isolate the solution for the tags before adding more onto the query.

Creating sorted tree in DOJO 1.6?

I new to learn dojo and trying to learn by it using samples code.
Using dojo 1.6
With help of sample codes , I created a tree
now i want to apply sorting on root and also on child.
With the help of this sample code , i changed the code
Output is not sorted n but the root folder has changed their position and child is deleted.
Plz help me to resolve this.
My code :
dojo.require("dojo.data.ItemFileWriteStore");
dojo.require("dojo.data.ItemFileReadStore");
dojo.require("dijit.tree.ForestStoreModel");
dojo.require("dijit.Tree");
var data = [ { id: 1, name: "answerTypeLabel", type:'scenario', children:[{_reference: 2}]},
{ id: 2, name: "acceptRequestLabel", type:'paragraph', data: "acceptRequestLabel"},
{ id: 3, name: "rejectRequestLabel", type:'scenario', children:[{_reference: 5},{_reference: 6}]},
{ id: 4, name: "MoreInformationLabel", type:'scenario', children:[{_reference: 7},{_reference: 8}]},
{ id: 5, name: "rejectRequestStatusLabel", type:'paragraph', data: "rejectRequestStatusLabel"},
{ id: 6, name: "rejectRequestNotCoveredLabel", type:'paragraph', data: "rejectRequestNotCoveredLabel" },
{ id: 7, name: "MoreInformationDocumentLabel", type:'paragraph', data: "MoreInformationDocumentLabel"},
{ id: 8, name: "MoreInformationDataLabel", type:'paragraph', data: "MoreInformationDataLabel"}
];
dojo.addOnLoad(function() {
var sortableStore = new dojo.data.ItemFileReadStore({
data: {
identifier: 'id',
label: 'name',
items: data
}
});
var model = new dijit.tree.ForestStoreModel({
rootLabel: 'Names',
store: new dojo.data.ItemFileWriteStore({
data: {
identifier: 'id',
items: [],
label: 'name'
}
}) // blank itemsstore
})
var tree = new dijit.Tree({
model: model,
updateItems: function(items) {
var self = this;
console.log('pre', this.model.root.children);
dojo.forEach(items, function(newItem) {
console.log('add', newItem);
try {
self.model.store.newItem({
id: sortableStore.getValue(newItem, 'id'),
name: sortableStore.getValue(newItem, 'name'),
type: sortableStore.getValue(newItem, 'type'),
data: sortableStore.getValue(newItem, 'data'),
});
} catch (e) {
console.log(e);
}
});
console.log('post', this.model.root.children);
console.log("children: ", this.rootNode.getChildren());
},
});
tree.placeAt(dojo.body());
sortableStore.fetch({
query: {
type:'scenario'
},
sort: [{
attribute: "name"}],
onComplete: function(items) {
console.log(items, 'sorted');
tree.updateItems(items);
}
})
});
Output :
The 'Names' origins from you setting 'rootLabel'.
Btw, fiddles have revisions and is simply a paste-bin like feature :)
You need to use the tree model pasteItem to insert referenced items (the 'children' property of each 'newItem').
Otherwise, there's another approach, if you get rid of the '_reference' structure of your data. See: http://jsfiddle.net/GHFdA/1/