How to query a range of values with Fauna and FQL? - faunadb

Im' having problem with FaunaDB. I'm new to it, went through docs, but no luck. I'll jump imto showing you the code right now but SO complains that my question has too much code in it.
I'm trying to do the following SQL statement with FQL:
SELECT * FROM order
WHERE cid = '1234'
AND fulfilled = false
AND rank >= 0
AND rank <= 100
I've tried the following:
q.Paginate(
q.Intersection(
q.Match(
q.Index('order_by_cid'),
'1234',
),
q.Match(
q.Index('order_by_status'),
false,
),
q.Range(
q.Match('order_by_rank'),
[0],
[100]
),
)
)
But this returns { data: [] }
My indexes:
{
ref: Index("order_by_cid"),
ts: 1602095185756000,
active: true,
serialized: true,
name: "order_by_cid",
source: Collection("order"),
terms: [{ field: ["data", "cid"] }],
partitions: 1
}
{
ref: Index("order_by_status"),
ts: 1602163027885000,
active: true,
serialized: true,
name: "order_by_status",
source: Collection("order"),
terms: [{ field: ["data", "fulfilled"] }],
partitions: 1
}
{
ref: Index("order_by_rank"),
ts: 1602611790710000,
active: true,
serialized: true,
name: "order_by_rank",
source: Collection("order"),
values: [{ field: ["data", "rank"] }, { field: "ref" }],
partitions: 8
}

The index should be:
CreateIndex(
{
name:'refByCidFulfilled',
source:Collection("order"),
terms:[{field:['data','cid']},{field:['data','fulfilled']}],
values:[{field:['data','rank']},{field:['ref']}]
}
)
And you can query
Map(
Paginate(
Range(
Match('refByCidFulfilled',[1234,false]),[1],[100])),
Lambda(['rank','ref'],Get(Var('ref')
)
)
)

Related

vuetable-2 select multiple sort items in same column

I need to filter data, including or excluding, multiple possible options in a column, but I don't know how to do it.
this only shows me a "single" select below the column name, with the possible options, but I can't select multiple of them, and I can't find an option to do that.
I need to filter by 2 rooms or multiple users, but the selection is not multiple, and there is no option to do it.
Now I have this HTML code:
<v-client-table id="messages" style="width:100%;" ref="table_reference" :options="table_options" :columns="table_fields" v-model="messages_array">
</v-client-table>
and this table configuration (messages, and other vars excluded):
const app2 = {
el: "#messages-container",
data() {
return {
table_options: {
filterByColumn: true,
texts: {
filterPlaceholder: ""
},
selectable: {
mode: 'single', // or 'multiple'
only: function(row) {
return true // any condition
},
selectAllMode: 'all',
programmatic: false
},
sortIcon: {
base: 'fa fas',
up: 'fa-long-arrow-alt-up',
down: 'fa-long-arrow-alt-down',
is: 'fa-sort'
},
listColumns: {
user_id: [],
room: [],
status: []
},
sortable: ['user_id', 'status', 'room', "created"],
filterable: ['user_id', "room", "status"],
headings: {
id: '#',
user_id: 'Name',
navigator_info: 'Details',
message: 'Message',
room: 'Room',
status: 'Status',
created: 'Date',
response_to: 'Actions'
}
},
table_fields: ["id", "user_id", "message", "room", "status", "created"],
}
}
};
I think this is a common use of a data table, and there should be a way to do it. I would appreciate your help. Thank you very much in advance!

How to get nested documents in FaunaDB with a filter?

The following query:
Paginate(Documents(Collection("backyard"))),
Lambda(
"f",
Let(
{
backyard: Get(Var("f")),
user: Get(Select(["data", "user"], Var("backyard")))
},
{
backyard: Var("backyard"),
user: Var("user")
}
)
)
)
results to:
{
data: [
{
backyard: {
ref: Ref(Collection("backyard"), "333719283470172352"),
ts: 1654518359560000,
data: {
user: Ref(Collection("user"), "333718599460978887"),
product: "15358",
date: "2022-06-06",
counter: "1"
}
},
user: {
ref: Ref(Collection("user"), "333718599460978887"),
ts: 1654517707220000,
data: {
email: "<email>",
name: "Paolo"
}
}
},
{
backyard: {
ref: Ref(Collection("backyard"), "333747850716381384"),
ts: 1654545603400000,
data: {
user: Ref(Collection("user"), "333718599460978887"),
product: "15358",
date: "2022-06-08",
counter: "4"
}
},
user: {
ref: Ref(Collection("user"), "333718599460978887"),
ts: 1654517707220000,
data: {
email: "<email>",
name: "Paolo"
}
}
}
]
}
How can I filter backyard by date without losing the nested users?
I tried:
Map(
Paginate(Range(Match(Index("backyard_by_date")), "2022-05-08", "2022-06-08")),
Lambda(
"f",
Let(
{
backyard: Get(Var("f")),
user: Get(Select(["data", "user"], Var("backyard")))
},
{
backyard: Var("backyard"),
user: Var("user")
}
)
)
)
However, the resultset is an empty array and the following already returns an empty array:
Paginate(Range(Match(Index("backyard_by_date")), "2022-05-08", "2022-06-08"))
My index:
{
name: "backyard_by_date",
unique: false,
serialized: true,
source: "backyard"
}
Maybe I have to adjust my index? The following helped me a lot:
How to get nested documents in FaunaDB?
How to Get Data from two collection in faunadb
how to join collections in faunadb?
Your index definition is missing details. Once that gets fixed, everything else you were doing is exactly right.
In your provided index, there are no terms or values specified, which makes the backyard_by_date index a "collection" index: it only records the references of every document in the collection. In this way, it is functionally equivalent to using the Documents function but incurs additional write operations as documents are created or updated within the backyard collection.
To make your query work, you should delete your existing index and (after 60 seconds) redefine it like this:
CreateIndex({
name: "backyard_by_date",
source: Collection("backyard"),
values: [
{field: ["data", "date"]},
{field: ["ref"]}
]
})
That definition configures the index to return the date field and the reference for every document.
Let's confirm that the index returns what we expect:
> Paginate(Match(Index("backyard_by_date")))
{
data: [
[ '2022-06-06', Ref(Collection("backyard"), "333719283470172352") ],
[ '2022-06-08', Ref(Collection("backyard"), "333747850716381384") ]
]
}
Placing the date field's value first means that we can use it effectively in Range:
> Paginate(Range(Match(Index("backyard_by_date")), "2022-05-08", "2022-06-08"))
{
data: [
[ '2022-06-06', Ref(Collection("backyard"), "333719283470172352") ],
[ '2022-06-08', Ref(Collection("backyard"), "333747850716381384") ]
]
}
And to verify that Range is working as expected:
> Paginate(Range(Match(Index("backyard_by_date")), "2022-06-07", "2022-06-08"))
{
data: [
[ '2022-06-08', Ref(Collection("backyard"), "333747850716381384") ]
]
}
Now that we know the index is working correctly, your filter query needs a few adjustments:
> Map(
Paginate(
Range(Match(Index("backyard_by_date")), "2022-05-08", "2022-06-08")
),
Lambda(
["date", "ref"],
Let(
{
backyard: Get(Var("ref")),
user: Get(Select(["data", "user"], Var("backyard")))
},
{
backyard: Var("backyard"),
user: Var("user")
}
)
)
)
{
data: [
{
backyard: {
ref: Ref(Collection("backyard"), "333719283470172352"),
ts: 1657918078190000,
data: {
user: Ref(Collection("user"), "333718599460978887"),
product: '15358',
date: '2022-06-06',
counter: '1'
}
},
user: {
ref: Ref(Collection("user"), "333718599460978887"),
ts: 1657918123870000,
data: { name: 'Paolo', email: '<email>' }
}
},
{
backyard: {
ref: Ref(Collection("backyard"), "333747850716381384"),
ts: 1657918172850000,
data: {
user: Ref(Collection("user"), "333718599460978887"),
product: '15358',
date: '2022-06-08',
counter: '4'
}
},
user: {
ref: Ref(Collection("user"), "333718599460978887"),
ts: 1657918123870000,
data: { name: 'Paolo', email: '<email>' }
}
}
]
}
Since the index returns a date string and a reference, the Lambda inside the Map has to accept those values as arguments. Aside from renaming f to ref, the rest of your query is unchanged.

Unknown column in sequelize count

I do such node.js Sequelize query to get rows quantity of included unread_messages, so I can get amount of unread messages of specifi user. But it returns me Unknown column 'unread_messages.id' in 'field list'.
If I remove attributes: {...} error disappears
const result = await Chats.findAndCountAll({
attributes: {
include: [[Sequelize.fn('COUNT', Sequelize.col('unread_messages.id')), 'total_unread_messages']]
},
where: {
...(req.query.filters as WhereOptions),
},
include: [
{ model: Users, as: 'createdBy', required: false },
{ model: ChatTypes, as: 'type', required: false },
{
model: ChatMessages,
as: 'unread_messages',
where: {
id: {[Op.gt]: Sequelize.literal(`(
SELECT last_read_message_id
FROM chats_users
WHERE
user_id = '${req.user?.id}'
AND
chat_id = Chats.id
)`),}
},
required: false,
},
{
model: ChatMessages,
as: 'last_message',
required: false,
include: [
{ model: Users, as: 'to_user' },
{ model: Users, as: 'from_user' },
{ model: Chats, as: 'chat' },
{ model: MessageTypes, as: 'message_type' },
{
model: Users,
as: 'is_mine',
required: false,
where: { id: req.user?.id },
},
],
},
],
group:['chats.id'],
order: req.query.sort as Order,
offset,
limit,
});

Sequelize: on a subset of model A, sum an integer-attribute of an associated model B

I want to do this:
select sum("quantity") as "sum"
from "orderArticles"
inner join "orders"
on "orderArticles"."orderId"="orders"."id"
and "orderArticles"."discountTagId" = 2
and "orders"."paid" is not null;
which results in on my data base:
sum
-----
151
(1 row)
How can I do it?
My Sequelize solution:
The model definitions:
const order = Conn.define('orders', {
id: {
type: Sequelize.BIGINT,
autoIncrement: true,
primaryKey: true
},
// ...
paid: {
type: Sequelize.DATE,
defaultValue: null
},
// ...
},
// ...
})
const orderArticle = Conn.define('orderArticles',
{
id: {
type: Sequelize.BIGINT,
autoIncrement: true,
primaryKey: true
},
// ...
quantity: {
type: Sequelize.INTEGER,
defaultValue: 1
}
},
{
scopes: {
paidOrders: {
include: [
{ model: order, where: { paid: {$ne: null}} }
]
}
},
// ...
})
Associations:
orderArticle.belongsTo(order)
order.hasMany(orderArticle, {onDelete: 'cascade', hooks: true})
I came up with this after hours of research:
db.models.orderArticles
.scope('paidOrders') // select only orders with paid: {$ne: null}
.sum('quantity', { // sum up all resulting quantities
attributes: ['quantity'], // select only the orderArticles.quantity col
where: {discountTagId: 2}, // where orderArticles.discountTagId = 2
group: ['"order"."id"', '"orderArticles"."quantity"'] // don't know why, but Sequelize told me to
})
.then(sum => sum) // return the sum
leads to this sql:
SELECT "orderArticles"."quantity", sum("quantity") AS "sum",
"order"."id" AS "order.id", "order"."taxRate" AS "order.taxRate",
"order"."shippingCosts" AS "order.shippingCosts", "order"."discount"
AS "order.discount", "order"."paid" AS "order.paid",
"order"."dispatched" AS "order.dispatched", "order"."payday" AS
"order.payday", "order"."billNr" AS "order.billNr",
"order"."createdAt" AS "order.createdAt", "order"."updatedAt" AS
"order.updatedAt", "order"."orderCustomerId" AS
"order.orderCustomerId", "order"."billCustomerId" AS
"order.billCustomerId" FROM "orderArticles" AS "orderArticles" INNER
JOIN "orders" AS "order" ON "orderArticles"."orderId" = "order"."id"
AND "order"."paid" IS NOT NULL WHERE "orderArticles"."discountTagId" =
'4' GROUP BY "order"."id", "orderArticles"."quantity";
which has this result on the same data base: 0 rows
If you know what I got wrong please let me know!
Thank you :)
Found the solution:
in the scopes definition on the orderArticle model:
scopes: {
paidOrders: {
include: [{
model: order,
where: { paid: {$ne: null}},
attributes: [] // don't select additional colums!
}]
}
},
//...
and the algorithm:
db.models.orderArticles
.scope('paidOrders')
.sum('quantity', {
attributes: [], // don't select any further cols
where: {discountTagId: 2}
})
Note: In my case it was sufficient to return the promise. I use GraphQL which resolves the result and sends it to the client.

Kendo UI BarChart Data Grouping

Not sure if this is possible. In my example I am using json as the source but this could be any size. In my example on fiddle I would use this data in a shared fashion by only binding two columns ProductFamily (xAxis) and Value (yAxis) but I would like to be able to group the columns by using an aggregate.
In this example without the grouping it shows multiple columns for FamilyA. Can this be grouped into ONE column and the values aggregated regardless of the amount of data?
So the result will show one column for FamilyA of Value 4850 + 4860 = 9710 etc.?
A problem with all examples online is that there is always the correct amount of data for each category. Not sure if this makes sense?
http://jsfiddle.net/jqIndy/ZPUr4/3/
//Sample data (see fiddle for complete sample)
[{
"Client":"",
"Date":"2011-06-01",
"ProductNumber":"5K190",
"ProductName":"CABLE USB",
"ProductFamily":"FamilyC",
"Status":"OPEN",
"Units":5000,
"Value":5150.0,
"ShippedToDestination":"CHINA"
}]
var productDataSource = new kendo.data.DataSource({
data: dr,
//group: {
// field: "ProductFamily",
//},
sort: {
field: "ProductFamily",
dir: "asc"
},
//aggregate: [
// { field: "Value", aggregate: "sum" }
//],
//schema: {
// model: {
// fields: {
// ProductFamily: { type: "string" },
// Value: { type: "number" },
// }
// }
//}
})
$("#product-family-chart").kendoChart({
dataSource: productDataSource,
//autoBind: false,
title: {
text: "Product Family (past 12 months)"
},
seriesDefaults: {
overlay: {
gradient: "none"
},
markers: {
visible: false
},
majorTickSize: 0,
opacity: .8
},
series: [{
type: "column",
field: "Value"
}],
valueAxis: {
line: {
visible: false
},
labels: {
format: "${0}",
skip: 2,
step: 2,
color: "#727f8e"
}
},
categoryAxis: {
field: "ProductFamily"
},
legend: {
visible: false
},
tooltip: {
visible: true,
format: "Value: ${0:N0}"
}
});​
The Kendo UI Chart does not support binding to group aggregates. At least not yet.
My suggestion is to:
Move the aggregate definition, so it's calculated per group:
group: {
field: "ProductFamily",
aggregates: [ {
field: "Value",
aggregate: "sum"
}]
}
Extract the aggregated values in the change handler:
var view = products.view();
var families = $.map(view, function(v) {
return v.value;
});
var values = $.map(view, function(v) {
return v.aggregates.Value.sum;
});
Bind the groups and categories manually:
series: [ {
type: "column",
data: values
}],
categoryAxis: {
categories: families
}
Working demo can be found here: http://jsbin.com/ofuduy/5/edit
I hope this helps.