nodejs sequelize include relation sorting - node.js

ha ve tow models one is Boat Master and another is boat price I want all boat data with its price and order by descending boat price the query is not working as expected its sorting data inside my relation and also the result is shown is sorted but its not picking up the boat who has price highest among all boats
db.BoatMaster.findAndCountAll({
distinct: true,
limit:request.params.pagesize,
offset:offsetpage,
attributes:[
'id',
'name',
'saleprice','length','cabins','year','berths','createdAt','updatedAt'
],
include:[
"boat_price",
],
order:[
['boat_price','price','DESC']
],
})
and here is the query output
SELECT
"BoatMaster".*,
"boat_price"."id" AS "boat_price.id",
"boat_price"."price" AS "boat_price.price",
"boat_price"."boatId" AS "boat_price.boatId",
"boat_price"."currency" AS "boat_price.currency",
"boat_price"."datefrom" AS "boat_price.datefrom",
"boat_price"."dateto" AS "boat_price.dateto"
FROM
(
SELECT
"BoatMaster"."id",
"BoatMaster"."name",
"BoatMaster"."saleprice",
"BoatMaster"."length",
"BoatMaster"."cabins",
"BoatMaster"."year",
"BoatMaster"."berths",
"BoatMaster"."createdAt",
"BoatMaster"."updatedAt"
FROM
"BoatMasters" AS "BoatMaster"
WHERE
(
SELECT
"boatId"
FROM
"boatprices" AS "boat_price"
WHERE
(
"boat_price"."boatId" = "BoatMaster"."id"
)
LIMIT
1
) IS NOT NULL
LIMIT
10 OFFSET 0
) AS "BoatMaster"
INNER JOIN "boatprices" AS "boat_price" ON "BoatMaster"."id" = "boat_price"."boatId"
ORDER BY
"boat_price"."price" DESC;
can anyone help me out what I am doing wrong here because data is not sorting according to the price?
thank in advanced

try this (if correct):
include:[
boat_price,
],
order:[
[boat_price,'price','DESC']
],
or
include:[
boat_price,
],
order:[
['boat_price.price','DESC']
],

Related

how to using a db function in where sentence via sequelize

I want to find an average value of this week and group by dayofweek, so I writen this sql, the sql is work well, but how can I achieve the same purpose via sequelize.
select dayofweek(datetime), avg(value) from Temperatures where week(datetime) = week(now()) group by dayofweek(datetime);
And here is my Temperatures table:
| field | type |
|----------|-------------|
| uuid | char(36) |
| value | float |
| datetime | datetime |
I've read the document of sequelize, but it seems that there is no clear explanation of how to using a function after where sentence, the condition is a function but not a field.
I have tried under way, but it's not work
where: {
[Sequelize.Op.eq]: [
sequelize.fn('week', Temperature.sequelize.fn('now')),
sequelize.fn('week', Temperature.sequelize.col('datetime')),
]
},
Thank your for your help!
You can use sequelize.fn for that , something like this :
[sequelize.fn('dayofweek', sequelize.col('datetime')), 'datetime']
For more details DO READ
Finally, I found the following method works well
return Temperature.findAll({
attributes: [
[Temperature.sequelize.fn('dayofweek', Temperature.sequelize.col('datetime')), 'dayofweek'],
[Temperature.sequelize.fn('AVG', Temperature.sequelize.col('value')), 'value'],
],
where: sequelize.where(sequelize.fn('week', Temperature.sequelize.fn('now')), sequelize.fn('week', Temperature.sequelize.col('datetime'))),
group: sequelize.fn('dayofweek', Temperature.sequelize.col('datetime')),
});
and if I need more conditional filters, just add an [Op.and] operator
return Temperature.findAll({
attributes: [
[Temperature.sequelize.fn('dayofweek', Temperature.sequelize.col('datetime')), 'dayofweek'],
[Temperature.sequelize.fn('AVG', Temperature.sequelize.col('value')), 'value'],
],
where: {
[Sequelize.Op.and]: [
sequelize.where(sequelize.fn('week', Temperature.sequelize.fn('now')), sequelize.fn('week', Temperature.sequelize.col('datetime'))),
]
},
group: sequelize.fn('dayofweek', Temperature.sequelize.col('datetime')),
});
here is the sql generated
SELECT dayofweek(`datetime`) AS `dayofweek`, AVG(`value`) AS `value` FROM `Temperatures` AS `Temperature` WHERE (week(now())=week(`datetime`)) GROUP BY dayofweek(`datetime`);

How to get the Vendor Name column from purchase order in suitescript 2.0

Disclaimer: I'm a NetSuite newbie.
I need to return both the item and the vendor name for all items in a purchase order. I Googled around and found this search.
The search works as desired.
var purchaseorderSearchObj = search.create({
type: "purchaseorder",
filters: [
["type","anyof","PurchOrd"], 'and',
['mainline','is','F'],'and',
['tranId','is',targetTranId.toString()]
],
columns: [
search.createColumn(
{ name: "itemid", join: "item" }
)
]
});
Now I need to add the Vendor Name column to the search.
I look for the purchase order objects description, and found it here (http://www.netsuite.com/help/helpcenter/en_US/srbrowser/Browser2017_1/script/record/purchaseorder.html).
I then try to modify the search by doing something like:
columns: [
search.createColumn(
{name: "itemid",join: "item"},
{name: "vendorname", join "item"})
]
. . . with no good result. I've tried {name: "vendorname"}, { name: "vendorname", join: "vendor"}, and other permutations.
What properties should I use for the 'columns' attribute to return item and vendorname?
How do I learn which columns need joining?
You need to call search.createColumn() again to create a new column:
columns: [
search.createColumn(
{name: "itemid",join: "item"}),
search.createColumn(
{name: "vendorname", join: "item"})
]

Sorting and placing matched values on top

I am using MongoDB and Node.js to display a record set in a page. I have got as far as displaying them on the page alphabetically, but I would like to display one row (the "default" row) at the top, and all the others alphabetically beneath it.
I know, I know, Mongo is definitely not SQL, but in SQL I would have done something like this:
SELECT *
FROM themes
ORDER BY name != "Default", name ASC;
or perhaps even
SELECT * FROM themes WHERE name = "Default"
UNION
SELECT * FROM themes WHERE name != "Default" ORDER BY name ASC;
I have tried a few variations of Mongo's sorting options, such as
"$orderby": {'name': {'$eq': 'Default'}, 'name': 1}}
but without any luck so far. I have been searching a lot for approaches to this problem but I haven't found anything. I am new to Mongo but perhaps I'm going about this all wrong.
My basic code at the moment:
var db = req.db;
var collection = db.get('themes');
collection.find({"$query": {}, "$orderby": {'name': 1}}, function(e, results) {
res.render('themes-saved', {
title: 'Themes',
section: 'themes',
page: 'saved',
themes: results
});
});
You cannot do that in MongoDB, as sorting must be on a specific value already present in a field of your document. What you "can" do is $project a "weighting" to the record(s) matching your condition. As in:
collection.aggregate(
[
{ "$project": {
"each": 1,
"field": 1,
"youWant": 1,
"name": 1,
"weight": {
"$cond": [
{ "$eq": [ "$name", "Default" ] },
10,
0
]
}
}},
{ "$sort": { "weight": -1, "name": 1 } }
],
function(err,results) {
}
);
So you logically inspect the field you want to match a value in ( or other logic ) and then assign a value to that field, and a lower score or 0 to those that do not match.
When you then $sort on that "weighting" first in order ( decending from highest in this case ) so that those values are listed before others with a lower weighting.

Sequelize produces invalid query "model.id AS model.id"

Here is the sequelize call I'm making to count favorites along with my model:
Model.findAll({
group: [ 'model.id', 'favorites.id' ],
attributes: [
'*',
[ Sequelize.fn('count', Sequelize.col('favorites.id')), 'favorites_count' ]
],
include: [
{ attributes: [], model: Favorite },
]
});
Here's the query it produces:
SELECT
model.id,
model.*,
count(favorites.id) AS favorites_count,
favorites.id AS favorites.id # Invalid!
FROM models AS model ...
Here's the error
ERROR: syntax error at or near "."
LINE 1: SELECT model.*, favorites.id AS favorites.id, ...
^
Because favorites.id is not a valid AS alias. Why does Sequelize produce this
invalid alias and how do I prevent it?
You cannot prevent it - sequelize needs to alias the column. The query becomes invalid because you have set quoteIdentifiers to false. The query sequelize wants is "favorites"."id" AS "favorites.id"
Why is sequelize doing such a "stupid" thing you might say. Well lets take an example:
SELECT "model"."id", "favorites"."id" ...
This produces the following result set:
[{ id: 42 }]
Because the two columns have the same name, they override each other so only one of the columns is returned. So we need to alias the favorites column so we get
[{ id: 42, 'favorites.id': 87 }]

Compound index query

I've got a query that i'm running that is pretty slow and am trying to do compound index on it, correctly, total newbie here. I've done the below index am just wondering if i've done it correctly, doesn't seem to have made a difference at all =/
Match.statics.getMatchesForDay = function (day, liveOnly, excludedAreas, excludedCompetitions, doneCallback) {
var include = "-_id match_id title date_utc date_iso _grouping match_info.period match_info.minute match_info.minute_extra match_info.full_time team_a team_b status time_utc";
var filter = {
date_utc: day,
score_coverage: true,
"_grouping._area.area_id": {
// Only include active areas
"$nin": excludedAreas
},
"_grouping._competition.competition_id": {
// Only include active competitions
"$nin": excludedCompetitions
}
};
if (liveOnly)
filter.status = "Playing";
this.find(filter).sort({
"_grouping._area.name": 1, //Sort by asc
"_grouping._competition.competition_id": 1, //Sort by asc
"date_iso": 1, //Sort by asc
}).select(include).exec(doneCallback);
};
Match.index({
date_utc: -1,
score_coverage: -1,
"_grouping._area.area_id": 1,
"_grouping._competition.competition_id": 1
});
Match.index({"_grouping._area.area_id": 1, "_grouping._competition.competition_id": 1, date_iso: 1});
My .explain() output:
{
"cursor" : "BtreeCursor date_utc_1_score_coverage_-1__grouping._area.area_id_1__grouping._competition.competition_id_1",
"isMultiKey" : false,
"n" : 358,
"nscannedObjects" : 358,
"nscanned" : 358,
"nscannedObjectsAllPlans" : 863,
"nscannedAllPlans" : 863,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 6,
"nChunkSkips" : 0,
"millis" : 7,
"indexBounds" : {
"date_utc" : [
[
"2015-03-15",
"2015-03-15"
]
],
"score_coverage" : [
[
true,
true
]
],
"_grouping._area.area_id" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
],
"_grouping._competition.competition_id" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : "xxxxx:27017",
"filterSet" : false
}
Unless it is working and i'm being picky, on a tiny collection it's around 200ms, on the larger ones 1-3s+. At the moment, the $nin is empty on both.
Thanks for looking.
That query won't be fast no matter what index you use. Let's look at the filter step-by-step:
var filter = {
date_utc: day,
Fine so far. An equality query can be indexed. Dates should have high enough selectivity. It's also likely to provide good data-locality.
score_coverage: true,
A boolean? Bad thing - indexes are essentially tree structures. If your datum is a single boolean, however, there's only two possible options: true and false. (low selectivity). This means that the tree has one true and one false branch that contain all the data 'below' it. That makes the tree become a linked list, essentially. It also destroys locality, because changing the value will have to rearrange entire sub trees. Move this to the end, and remove it from the index.
"_grouping._area.area_id": {
// Only include active areas
"$nin": excludedAreas
},
Indexes work like the letter marks in phone books. You're looking for "john doe"? Fine, look up the letter "D" visible from the outside (the index), then search for the "o" in "Do", and so forth. Suppose I gave you a phone book and asked you to find all the poeple that are NOT named "Doe". Does the index help? Not really, it would have been easy to skip "Doe". After all, you'll need to go through the whole thing anyway. Again, this is a problem of low selectivity.
"_grouping._competition.competition_id": {
// Only include active competitions
"$nin": excludedCompetitions
}
Same argument, $nin on large amounts of data is bad.
Now, the sorting:
this.find(filter).sort({
"_grouping._area.name": 1, //Sort by asc
"_grouping._competition.competition_id": 1, //Sort by asc
"date_iso": 1, //Sort by asc
}).select(include).exec(doneCallback);
Sorting is relatively expensive operation, so you'll want to ensure your indexes match the following rule because then the data is already sorted in the index:
equality criteria -- range criteria -- sort criteria
But now you have turned around the order of date-area-competitionId used in the equality and range criteria to area-competitionId-date for sorting.
Solving this requires understanding of the problem domain. I suggest you try to rearrange the data structure based on query selectivity / locality concerns. Queries should be simple.

Resources