Is it possible to omit a single query log while using Sequelize?
For obvious reason I want to know every query shot by my NodeJs server, but I have one that is tied to a recursive function that works like a printing spooler and it's spamming my server log.
Cheers
Yes, it's possible.
If you want to omit logging from a plain query, use this code:
sequelize
.query('SELECT ...', null, {
logging: false
});
If you want to disable logging when finding an object ORM-style, use this syntax:
Model.findAll({
where: {
id: 123
},
logging: false
});
The official documentation where this information is from can be found at http://docs.sequelizejs.com/en/latest/api/model/#findall.
Related
I have a hard time figuring out how to programatically get specific GCP log entries.
I have multiple Cloud Functions in my project. They all write logs to a log named cloudfunctions.googleapis.com%2Fcloud-functions (maybe it is possible to have separate logs for each cloud function but that is another question I should ask I guess :-)
By using the client library for logging I do the following to retrieve a few log entries, which works fine:
const log = logging.log('cloudfunctions.googleapis.com%2Fcloud-functions');
const [entries] = await log.getEntries({
autoPaginate: false,
pageSize: 5
});
However, I now want to retrieve only entries from one of my cloud functions (function-x) and try to find any details on what to put in the query object for the log.getEntries(query) call. As most GCP users know, finding API information in GCP is sometimes a bit of a hustle... The closest I've gotten regarding the API method above is this page. It list a public resourceNames: string[] property which I try to use, but apparently I do something wrong and need help.
I try e.g.
const [entries] = await log.getEntries({
autoPaginate: false,
pageSize: 5,
resourceNames: ['projects/my-project-id/function-x']
});
But cannot get it to work. I just get an
Error: 3 INVALID_ARGUMENT: Received unexpected value parsing name "projects/my-project-id/logs/cloudfunctions.googleapis.com%2Fcloud-functions/function-x": my-project-id. Expected the form projects/[PROJECT_ID]
So, my question is: How do I do to get log entries from function-x only?
As specified in the page defining resourceNames, the query object also has a filter property but no details on how to use it. A second question is therefore how can this filter property be used? What format does it require? (Once I can retrieve logs from my function I would for example like to filter them on labels and severity).
Finally figured out the response to this (my) question. If I use teh following it works:
const [entries] = await log.getEntries({
autoPaginate: false,
pageSize: 5,
filter: 'resource.labels.function_name=function-x',
resourceNames: ['projects/my-project-id']
});
Turns out, as documented here, resourceNames should be one of
projects/[PROJECT_ID]
organizations/[ORGANIZATION_ID]
billingAccounts/[BILLING_ACCOUNT_ID]
folders/[FOLDER_ID]
and the function name should be placed in the filter instead.
Any way to do a bulk update, create using sequelize and postgres?
I have tried the following:
sequelize.models.Location.bulkCreate(updatedPost.locations,
{ ignoreDuplicates: true }).then(function (locations) {
res.send(updatedPost);
res.end();
});
I got this error:
postgres does not support the 'ignoreDuplicates' option.
INSERT ... ON CONFLICT DO NOTHING/UPDATE is a thing on Postgres now. They have really good documentation. So you could do Sequelize.query() to do it.
But I'm sorry Sequelize still does not support it natively. You have to write a method on your model to do it.
I'm working on a custom adapter in sails#0.10.0-rc4 which will support associations but I am having trouble getting them working in conjunction with my adapter. My configuration is a one-to-many association between article and stats. My models and adapter are setup like this:
// api/models/article.js
module.exports = {
connection: ['myadapter'],
tableName: 'Knowledge_Base__kav',
attributes: {
KnowledgeArticleId: { type: 'string', primaryKey: true }
stats: {
collection: 'stats',
via: 'parentId'
}
}
// api/models/stats.js
module.exports = {
connection: ['myadapter'],
tableName: 'KnowledgeArticleViewStat',
attributes: {
count: 'integer',
ParentId: {
model: 'article'
}
}
}
// adapter.js
find: function(connectionName, collectionName, options, cb) {
console.dir(options)
// output
// {where: null}
db.query(options, function(err, res)) {
cb(err, res)
}
}
However, when I try to populate using Article.find().populate('stats').exec(console.log()), my adapter gets {where: null} as options when I would expect it to receive {where: {parentId: [<some-article-id>]}}. It will return a list of articles to me but the field which is supposed to be populated from another model (stats) is just an empty list.
I feel like this is related to the fact that my adapter is not getting the proper where param to search for the related model on the primary key. To test this further, I setup a test one-to-many relationship using the the sails-mongo adapter. In this case the adapter did receive params I expected and the association worked fine.
Does anyone have any idea on why .populate('stats') wouldn't be sending the proper "where" params to my adapter?
Update 3/7
So it seems like what happens in associations is that SomeModel.find() will hit the adapter once and then .populate('othermodel') hits the adapter again using the primary key of the first request. Then the results of both are joined together. In my case, the second hit against the adapter isn't happening for some unknown reason.
Update
The original issue was related to an attribute naming error that's mentioned in the comments below. However, there still appears to be some issue with the final population step mentioned by particlebanana:
Final step will: Take all of the query results from all the returned query operations
and combine them in-memory to build up a result set you can return in
the exec callback.
I'm seeing that all required queries are now firing but they are failing to actually populate the alias. Here's the call with some added debugging output in the form of a gist for easier consumption: https://gist.github.com/jasonsims/9423170
It looks like you are on the right track! The way the operation sets get built up, the .find() on the Article should run with the first log (empty where) and the second query should get run with the parentId criteria in the log. The second query isn't running because it can't build up that parentId array of primary keys when you don't return anything from the first query.
Short answer: you need to return something in the find callback to see the second log, which should match your expected criteria.
The query lifecycle looks something like this:
Check if all query pieces are on the same connection, if not break out which queries will run on which connections
For all queries on a single connection, check if the adapter supports native joins (has a .join() method, if so you can pass the criteria down and let the adapter handle the joins.
If no native join method is defined run the "parent" operation (in this case the Article.find())
Use the results of the parent operation to build up criteria for any populations that need to run. (The parentId array in your criteria) and run the child results.
Take all of the query results from all the returned query operations and combine them in-memory to build up a result set you can return in the exec callback.
I hope that helps some. Shoot me the url of your repo and I will look through it, if it's able to be open sourced, and can help some more if you come across any issues.
Just to summarize, there were multiple issues going on here which were causing associations not to populate:
Custom primary keys
There was a problem with waterline when joining data from models using custom primary keys. #particlebanana fixed this in 8eff54b and it should be included in the next rc of waterline (waterline#0.10.0-rc5).
Malformed SOQL query
When waterline queries the adapter for a second time in order to acquire the child rows, it does so using { foreignKey: [ value ] }. Since the value was a list, jsforce was incorrectly generating the SOQL query since it expected all list values to be accompanied by either $in or $nin operators. I addressed this issue in github/jsforce#9 and it's now included in jsforce#1.1.2.
Model attributes are case sensitive
The models in my project were defined in snakeCase but the json response from Salesforce was using EveryWordCapitalized. This causes 1-to-many joins in waterline to reduce the many child records to one when it runs _.uniq(childRows, pk). Since the model has defined pk == id but the actual value returned from Salesforce is pk == Id, this call to uniq blows away all child records but one. I'm not entirely sure if this should be a waterline bug or not but fixing the capitalization in the model attribute definitions resolved this.
I want to see the SQL commands that are sent to the PostgreSQL server because I need to check if they are correct. In particular, I am interested in the table creation commands.
For instance, ActiveRecord (Ruby) prints its SQL statements to standard output. Is this possible with Node.js/ActionHero.js and Sequelize.js as well?
You can pass a logging option when initializing sequelize, which can either be a function or console.log
var sequelize = new Sequelize('database', 'username', 'password', {
logging: console.log
logging: function (str) {
// do your own logging
}
});
You can also pass a logging option to .sync if you only want to view the table creation queries
sequelize.sync({ logging: console.log })
As stated in the log Error: Please note that find* was refactored and uses only one options object from now on.. For the latest sequelize version (4) if you want to have the result for only one command:
User.findAll({where: {...}, logging: console.log})
If you want to look at the sequelize for one command you can listen to it and attach a function to the print the sql.
Check out this example:
User.find(1).on('sql', console.log).then(function(user) {
// do whatever you want with the user here
You can also take advantage of Sequelize's use of the Debug module, by setting your environment, thus:
DEBUG=sequelize:sql*
before starting your app.
I'm trying to utilize MongoDB 2.4 experimental text search feature from within nodejs. The only problem is, native nodejs mongo drivers don't seem to support collection-level runCommand, as far as I can tell.
The Mongo shell syntax looks like this:
db.collection.runCommand( "text", { search : "Textvalue" } );
There is a db.command / db.executeDbCommand function it appears, but I don't know how to choose a collection and run the text command using it (if it is possible), as it needs to be on the collection level and not the db level.
Any help would be appreciated
I managed to get it working through a combination of Asya Kamsky's comment, by utilizing
this.db.command({text:"collection" , search: "phrase" }).
The problem was it isn't returned like a standard result so a toArray() call was failing. Instead, I put the callback directly inside:
this.db.command({text:"collection" , search: "phrase" }, function(err, cb){