convert query from mysql client to sequelize syntax - mysql

i working sequelize with nodejs , i try convert my query codes from mysql query to sequelize syntax can you help me on this ?
mysql query :
select username,message,fromUserId,toUserID from messages inner join messageToUsers on messages.id = messageToUsers.messageID left outer join users on messages.fromUserID = users.id where messageToUsers.`toUserID` = 5 and messages.`fromUserId` = 7 or messageToUsers.`toUserID` = 7 and messages.`fromUserId` = 5
sequlize query
Message.hasMany(MessageToUser,{foreignKey:'messageID'});
Message.belongsTo(Users,{foreignKey:'fromUserId'});
Message.findAll({where:{fromUserId :5,fromUserID : 7},
include :[
{model:MessageToUser,where:{toUserID:5,toUserID:7}} ,
{model:Users,attributes:['id','username']}
]
}).then(function(messages) {
console.log(JSON.stringify(messages));
res.status(200).json(messages);
})

You are missing your attributes
Message.hasMany(MessageToUser,{foreignKey:'messageID'});
Message.belongsTo(Users,{foreignKey:'fromUserId'});
Message.findAll({where:{fromUserId :5,fromUserID : 7},
include :[
{model:MessageToUser,where:{toUserID:5,toUserID:7}} ,
{model:Users,attributes:['id','username']}
],
attributes: ["username","message", "toUserId", "fromUserId"] //<-HERE
}).then(function(messages) {
console.log(JSON.stringify(messages));
res.status(200).json(messages);
}); //<- you also missed a semicolon here.
Second thing I noticed. If you use the same field two times in the same Model in your where, one of them will be ignored. You need to use $and.
{model:MessageToUser,where:{
$and: {[toUserID:5],
[toUserID:7]}
}}
Note: missing semicolons at the end of a statement usually won't cause your application to fail but is best practice to be consistent, either always use them or always omit them.

i fixed this problem thanks everybody
Message.hasMany(MessageToUser,{foreignKey:'messageID',as: 'model1'});
Message.belongsTo(Users,{foreignKey:'fromUserId'});
Message.findAll({where:{$or:[{'$model1.toUserId$':toUserId,fromUserId:fromUserID},{'$model1.toUserId$':fromUserID,fromUserId:toUserId}]},
include :[
{attributes: ["toUserId"],model:MessageToUser,as: 'model1'} ,
{attributes: ["username"],model:Users}
]
}).then(function(messages) {
console.log(JSON.stringify(messages));
res.status(200).json(messages);
});

Related

Sequelize $ne is not working like expected

I'm using mysql, when I try to run this query:
Order.findAll({
where: {
end_date: {
$ne: null,
},
},
});
The where clause it generates looks like this:
where: "`Order`.`end_date` = '2020-03-11 03:00:00'
I tried using $nin and $not, I also tried using a raw query, and I still get the same result.
I see there was a bug with sequelize and mysql a few versions behind, but it seems like it was fixed on 5.19.5, and I'm using v 5.21.5.
Mysql version is 5.7.29
Can anyone help me with this?
Edit: Found a solution somewhere else, all I had to do was use [Op.not]. In case anyone needs this as well.
That won't work with sequelize v5. Here is the way to go.
const Op = require('sequelize').Op
Order.findAll({
where: {
end_date: {
[Op.ne]: null,
},
},
});
You can read more about using operators here.
Deprecation warning here.

Using N1QL reserved words

I have a document with the structure { doc.data.role.level }, I want to access to level property,
but using this query
SELECT r.data.role.level FROM `hostel` r where r.id = '12345678Z'
I got the error
"msg": "syntax error - at role",
but with those query I got no results
SELECT r.data.`role`.level FROM `hostel` r where r.id = '12345678Z'
SELECT `r.data.role.level` FROM `hostel` r where r.id = '12345678Z'
If there are special characters in fields/identifiers or reserve keywords you must escape them with back-ticks(i.e. escaped identifiers) as described https://docs.couchbase.com/server/current/n1ql/n1ql-language-reference/identifiers.html
Example 1:
"role" is reserve keyword
{
"id":"12345678Z",
"data":{"role":{"level":3}}
}
SELECT r.data.`role`.level
FROM hostel AS r
WHERE r.id = "12345678Z";
Example 2:
Field has special character dot. You must escape whole field name (to interpret as field vs nested document).
{
"id":"12345678Z",
"data.role.level":5
}
SELECT r.`data.role.level`
FROM hostel AS r
WHERE r.id = "12345678Z";
Example 3:
hostels is array. If you are looking inside array you must use ANY syntax.
{
"hostels": [ { "id":"12345678Z"},
{ "id":"34545678Z"}}
]
"data":{"role":{"level":3}}
}
SELECT r.data.`role`.level
FROM hostel AS r
WHERE ANY h IN r.hostels SATISFIES h.id = "12345678Z" END;
You're on the right track with backticks to escape reserved words.
If you aren't getting an error message, then I suspect it's your WHERE clause. Are you sure your documents have an "id" field in them?
{ "id": "12345678Z", "foo": "bar", ... etc ... }
Or are you trying to query based on the document ID (in the below screenshot there is no "id" field in the document)?
If the latter, then you should use META().id:
SELECT * FROM `testbucket` r where META(r).id = '12345678Z'
I know this might seem a bit confusing, but "id" isn't a magic field in Couchbase. It's a field just like any other. The actual ID of the document is in the document's metadata.
Also, a recommendation: if you are trying to get a single document by its ID, you're much better off using the key/value API instead of a N1QL query. No need to involve the overhead of query/index services.

Get select fields from find method from mysql Database in Moleculer Framework

Can you please suggest how to get select fields from find method ?
e.g
let params = {
limit,
offset,
query: request
};
this.adapter.find(params)
Here, this will return all fields but instead of this I need only account_id from the resultset. I've already tried with fields inside params as well as settings{ fields: ["accout_id", "username"]} but doesn't work.
e.g
fields: ["account_id"]
Please guide me.
Thanks
Yes... I got the solution. I've used 'this.model' intead of 'this.adapter' like following way.
let params = {
limit,
offset,
query: request
};
this.model.find({
attributes: ['account_id'],
where : first_name : {
$like: '%Adam%'
}
})

couchbase N1ql query select with non-group by fields

I am new to couchbase and I have been going through couchbase documents and other online resources for a while but I could't get my query working. Below is the data structure and my query:
Table1:
{
"jobId" : "101",
"jobName" : "abcd",
"jobGroup" : "groupa",
"created" : " "2018-05-06T19:13:43.318Z",
"region" : "dev"
},
{
"jobId" : "102",
"jobName" : "abcd2",
"jobGroup" : "groupa",
"created" : " "2018-05-06T22:13:43.318Z",
"region" : "dev"
},
{
"jobId" : "103",
"jobName" : "abcd3",
"jobGroup" : "groupb",
"created" : " "2018-05-05T19:11:43.318Z",
"region" : "test"
}
I need to get the jobId which has the latest job information (max on created timestamp) for a given jobGroup and region (group by jobGroup and region).
My sql query doesn't help me using self-join on jobId.
Query:
/*
Idea is to pull out the job which was executed latest for all possible groups and region and print the details of that particular job
select * from (select max(DATE_FORMAT_STR(j.created,'1111-11-11T00:00:00+00:00')) as latest, j.jobGroup, j.region from table1 j
group by jobGroup, region) as viewtable
join table t
on keys meta(t).id
where viewtable.latest in t.created and t.jobGroup = viewtable.jobGroup and
viewtable.region = t.region
Error Result: No result displayed
Desired result :
{
"jobId" : "102",
"jobName":"abcd2",
"jobGroup":"groupa",
"latest" :"2018-05-06T22:13:43.318Z",
"region":"dev"
},
{
"jobId" : "103",
"jobName" : "abcd3",
"jobGroup" : "groupb",
"created" : " "2018-05-05T19:11:43.318Z",
"region" : "test"
}
If I understand your query correctly, this can be answered using 'group by' and no join. I tried entering your sample data and the following query gives the correct result:
select max([created,d])[1] max_for_group_region
from default d
group by jobGroup, region;
How does it work? It uses 'group by' to group documents by jobGroup and region, then creates a two-element array holding, for every document in the group:
the 'created' timestamp field
the document where the timestamp came from
It then applies the max function on the set of 2-element arrays. The max of a set of arrays looks for the maximum value in the first array position, and if there's a tie look at the second position, and so on. In this case we are getting the two-element array with the max timestamp.
Now we have an array [ timestamp, document ], so we apply [1] to extract just the document.
I'm seeing some inconsistencies and invalid JSON in your examples, so I'm going to do the best I can. First off, I'm using Couchbase Server 5.5 which provides the new ANSI JOIN syntax. There might be a way to do this in an earlier version of Couchbase Server.
Next, I created an index on the created field: CREATE INDEX ix_created ON bucketname(created).
Then, I use a subquery to get the latest date, aggregated by jobGroup and region. I then join the latest date from this query to the entire bucket and select the fields that (I think) you want in your desired result:
SELECT k.jobId, k.jobName, k.jobGroup, k.created AS latest, k.region
FROM (
SELECT j.jobGroup, j.region, MAX(j.created) as latestDate
FROM so j
GROUP BY j.jobGroup, j.region
) dt
LEFT JOIN so k ON k.created = dt.latestDate;
Problems with this approach:
If two documents have the exact same date, this isn't a reliable way to determine the latest. You can add a LIMIT 1 to the subquery, which would just pick one arbitrarily, or you could ORDER BY whatever your preference is.
Subquery performance: I don't know how large your data set is, but this could be pretty slow.
Requires Couchbase Server 5.5, which is currently in beta.
If you are using a different version of Couchbase Server, you may want to consider asking in the Couchbase N1QL Forums for a more expert answer.

MySQL to MongoDB query translation

I need to convert following mysql query to mongo.
Any help will be highly appreciated.
SELECT cr.*, COUNT(cj.job_id) AS finished_chunks FROM `checks_reports_df8` cr
LEFT JOIN `checks_jobs_df8` cj ON cr.id = cj.report_id
WHERE cr.started IS NOT NULL AND cr.finished IS NULL AND cj.is_done = 1
MongoDB doesn't do JOINs. So you will have to query both collections and do the JOIN on the application layer. How to do this exactly depends on which programming language you use to develop your application. You don't say which one you use, so I will just give you an example in JavaScript. When you use a different language: The second snippet is just a simple FOR loop.
These are the MongoDB queries you would use. I don't have access to your data, so I can not guarantee correctness.
var reports = db.checks_reports_df8.find({
"started": {$exists: 1 },
"finished": {$exists: 0 }
});
This query assumes that your null-values are represented by missing fields which is normal practice in MongoDB. When you have actual null values, use "started": { $ne: null } and "finished": null.
Then iterate over the array of documents you get. For each RESULT perform this query:
reports.forEach(function(report) {
var job_count = db.checks_jobs_df8.aggregate([
{$match: {
"report_id": report.id,
"is_done": 1
}},
{$group: {
_id: "$job_id",
"count": { $sum: 1 }
}}
])
// output the data from report and job_count here
});