Query array of objects in Sequelize - javascript

How can I query this data with name, what should I write in where clause?
{a: [{name: 'test'}, {name: 'test2'}]}
The example bellow is for first element only. I would like to have for every index.
a: {
0: {
name: value
},
},

Query by name using pure SQL.
await sequelize.query(
SELECT
*
FROM
table_name
WHERE
a->>'name' = 'something';
);
Converting this to sequelize functions should be something equivalent to this query.
Model.findAll<Model>({
where: { 'a': { name: 'something' } }
});
EDIT AFTER THE COMMENT:
I couldn’t find sequelize function for jsonb_array_elements, so I hope a pure SQL query can help.
await sequelize.query(
SELECT * FROM table_name, jsonb_array_elements(table_name.jsonb_column_name) with ordinality arr(item_object)
WHERE item_object->>'name' = 'test';
)
// jsonb_column_name is the same as a

Related

Sequelize - Delete association records from parent instance

I am trying to find a way to remove rows from the DB through the parent model (menu) that has many children (foods). I only want to delete certain rows though, not all.
Menu.js
...
Menu.hasMany(models.Food, {
as: 'foods',
foreignKey: 'menuId',
sourceKey: 'id'
});
...
In my controller I have the following to try and delete certain foods off the menu.
...
const result = await menu.destroyFoods({
where: {
name: ['Pasta', 'Pizza']
}
});
...
I have also tried singular destroyFood as well. For both I am getting destoryFood/destoryFoods is not a function. Is there any easy way to do this from the instance of menu? New to sequelize, would love some help. Thanks.
Thanks
You can use menu.removeFoods() and menu.removeFood() - see Special methods/mixins added to instances: Foo.hasMany(Bar) for more information.
You will also need to use the Op.in query operator to specify multiple values for Food.name.
const { Op } = require('sequelize');
const result = await menu.removeFoods({
where: {
name: {
[Op.in]: ['Pasta', 'Pizza'],
}
}
});
This is the equivalent of calling Food.destroy() where the menuId is equal to the menu.id from the earlier result.
const results = await Food.destroy({
where: {
menuId: menu.id,
name: {
[Op.in]: ['Pasta', 'Pizza'],
},
},
});

Parsing sql query to JSON

I'm looking for a way, preferable an NPM Package, to parse an SQL query to JSON. I found some for SELECT statements, but I actually need for UPDATE and INSERT INTO statements.
For example, a Query in the form of
"UPDATE "users" SET name = $2 where id in ($1)", ['new name', 1]
The result should be something like:
{
action: 'UPDATE',
entity: 'users',
values: { name: 'new name' },
conditions: { 'id': 1}
}
Thank you for your help!
Welcome to StackOverflow!
There are multiple libraries out there for doing this. One example is node-sql-parser. Based on their readme, you can simply do:
const { Parser } = require('node-sql-parser');
const parser = new Parser();
const ast = parser.astify('SELECT * FROM t'); // mysql sql grammer parsed by default
console.log(ast);
And the output would be something like this:
{
"type": "select",
"columns": "*",
"from": [
{
"table": "t"
}
]
}
You can play around with it here to see if it matches your expectations: https://npm.runkit.com/node-sql-parser.

MongoDB: Updating array item in collection is not working

I have a structure like this:
{
...
_id: <projectId>
en-GB: [{
_id: <entryId>,
key: 'some key',
value: 'some value',
}]
}
And I've tried updating it with Mongoose (and raw mongodb too) like this:
const result = await Project
.update({
_id: projectId,
'en-GB._id': entryId,
}, {
$set: {
'en-GB.$.key': 'g000gle!!',
},
})
.exec();
I've checked that the IDs are correct. But it doesn't update anything:
{ n: 0, nModified: 0, ok: 1 }
What am I doing wrong? Thanks
As discussed in the comments on the question, the issue is directly related to passing in a string representation of an id in the query as opposed to using an ObjectId. In general, it's good practice to treat the use of ObjectIds as the rule and the use of string representations as special exceptions (e.g. in methods like findByIdAndUpdate) in order to avoid this issue.
const { ObjectId } = require('mongodb');
.update({
_id: ObjectId(projectId),
'en-GB._id': ObjectId(entryId),
})

How to extend/modify the object in nodejs api?

i am using the angular-fullstack yeoman generator. created a schema for a Product, and a set of api crud operations. all works well. now in the get list operations, i don't want to receive all the fields, only a subset. like a select in sql. i would also wish to alter one value. instead of the price, i need price * 1.1 .
how to do that?
here is the code for the index method (returns list of products):
// Gets a list of Products
export function index(req, res) {
Product.findAsync()
.then(respondWithResult(res))
.catch(handleError(res));
}
function respondWithResult(res, statusCode) {
statusCode = statusCode || 200;
return function(entity) {
if (entity) {
res.status(statusCode).json(entity);
}
};
}
As stated in the documentation, .find() takes two params, query and projection.
// params
Product.findAsync(query, projection)
You can use projection to "select" a subset of fields;
// example
Product.findAsync({}, { _id: 1, name: 1, description: 1 })
// result, only the three specified field will be returned
[
{ _id: 'abc123', name: 'Some name', description: 'Some description'},
{...}
]
If you want to manipulate data I think you have to use the aggregation pipeline

Node.js Sequelize ManyToMany relations producing incorrect SQL

I'm having a problem with sequelize ManyToMany relations.
Here are my models...
var db = {
players: sequelize.define('players', {
name: Sequelize.STRING
}),
teams: sequelize.define('teams', {
name: Sequelize.STRING
}),
init: function() {
this.players.hasMany(this.teams, {joinTableName: 'teams_has_players'});
this.teams.hasMany(this.players, {joinTableName: 'teams_has_players'});
this.players.sync();
this.teams.sync();
}
};
Here's the find
db.players.findAll({
where: {team_id: 1},
include: ['teams']
}).success(function(results) {
// print the results
});
The above find will produce the following SQL:
SELECT
players . *,
teams.name AS `teams.name`,
teams.id AS `teams.id`
FROM
players
LEFT OUTER JOIN
teams_has_players ON teams_has_players.player_id = players.id
LEFT OUTER JOIN
teams ON teams.id = teams_has_players.team_id
WHERE
players.team_id = '1';
What appears to be wrong with this is that the WHERE statement should be WHERE teams.team_id = '1'
Where am I going wrong with this?
Thanks in advance
Hmm actually everything looks quite OK-ish. db.players.findAll with where: { team_id: 1 } should create a query with WHERE players.team_id = '1'. That's perfectly expected. Also, you teams won't have a team_id but an id instead. However, there is a good chance that include is broken atm.

Categories

Resources