Meteor - Mongo Write error - mongodb

I am getting an unexpected error when i attempt an update with the latest version of meteor.js. The type error doesn't specify which field it fails on and i am not sure if this is a mongo related issue or not. Has anyone seen this error before?
Error in Mongo write: TypeError: boolean is not a function
I20130901-19:44:56.515(-5)? at writeCallback (packages/mongo-livedata/mongo_driver.js:206)
I20130901-19:44:56.515(-5)? at Meteor.bindEnvironment.runWithEnvironment (packages/meteor/dynamics_nodejs.js:69)
I was able to stop my client from blocking by specifying a callback to the server side call.
https://gist.github.com/warsamebashir/6408451

This usually happens to me when I pass {multi:true} as a second argument to Collection.remove on the server.

You're calling Collection.update with 5 arguments, which is a little bit too many. Read about it in the docs.

I'm getting the same thing on this code:
Templates.remove({_id: {$in: templateIDs}}, {multi:true});
Just for the record, I am still on 0.7.0 and this type of query was working perfectly before the 0.8.1 release. How the hell is it affecting the old 0.7.0 without me even updating is beyond comprehension. Did they change the behavior of remove to now automatically do {multi: true} on everything it finds, because that's what I understood from Peppe L-G's link.
Edit1: Follow-up, yes removing the , {multi:true} fixed the problem, while it still does delete all the matched documents in mongodb. It's either me updating mongodb to 2.4.10 from 2.4.9 or they did an update on the 0.7.0 release that fixes Meteor's behavior.

Related

mongoclient db.databaseName always returns admin

I'm using nodejs mongodb module v2.2.34
When I connect to a DB using this format:
mongodb+srv://<username>:<password>#MYATLASSERVER.azure.mongodb.net/mydatabase
db.databaseName always returns admin instead of mydatabase.
Why would this happen and how do I get it to return mydatabase as expected?
Thanks!
OK, I think I found the solution
updated the driver to 3.5 and then used:
db.s.options.dbName
seems like a weird object path to get the name from
It's annoying that mongo keeps changing the paths of things with driver / version updates. But I guess that's what we gotta deal with. Feel free to post other solutions if there are more stable ways of doing this. Or to explain why this change was made.

MongoDB collection shorthand?

Newbie alert.All this while I'm using the below command to refer to specific collection as below
db.collection('someCollection')
But example shared on this link, clearly there's a shorthand available as below
db.products
So I go ahead and change it from db.collection('someCollection').update(...) to db.someCollection.update(...), but i'm getting exception
(node:51451) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'update' of undefined
Example from the doc is for mongodb shell. Which, although also using javascript, is a completely different environment from node.js driver. From a brief glance at the driver's documentation, looks like it does not support this sugar/shorthand.

Npgsql syntax error at or near "DISCARD"

I'm running a standard query against Redshift, and every other time I run it, I get:
[ConciergeClientException: We encountered a problem fulfilling your request: 42601: syntax error at or near "DISCARD"]
I'm opening and closing the connection properly, and the query looks fine. I've queried Redshift's STL_QUERY and the statement looks fine. I turned on logging, and I can't see where this DISCARD command is being sent.
Yet every other query gives me this error.
Thoughts?
Assuming you're using Ngsql 3.2.0, this looks like a duplicate of https://github.com/npgsql/npgsql/issues/1426. In a nutshell, Npgsql's pooling was changed in 3.2.0 in a way which is incompatible with Reshift.
As a workaround, specify No Reset On Close in your connection string. This will be fixed for 3.2.1.

Upsert in waterline ORM (Sails.js)

I am looking for a way to perform MongoDB's upsert operation in waterline. One way is to use the native method.
Model.native(function (err, Collection){
Collection.update({"key": "val"}, {"$set": {"x": "val"}}, {"upsert": true}, function (err, updated){
// do something
})
})
But if I don't want to use native, I could see on similar function findOrCreate, which creates a new entry if the item does not exist. However, I could not find a way to update the item if it exists. Is that possible or one has to use the native method only for that ?
Note: I am using Sails 0.11
As of now (v0.10.26) there is no way of doing a Mongo-style upsert besides the ones you've mentioned. This keeps coming up every once in a while but I couldn't find an issue addressing it directly, so maybe you could raise one.
Update
This issue talks about updateOrCreate and the linked threads suggest this might be added soon. I was looking into the Sails issues initially so no wonder I found nothing.

Conditional update for MongoDB (Meteor)

TLDR: Is there a way I can conditionally update a Meteor Mongo record inside a collection, so that if I use the id as a selector, I want to update if that matches and only if the revision number is greater than what already exists, or perform an upsert if there is no id match?
I am having an issue with updates to server side Meteor Mongo collections, whereby it seems the added() function callback in the Observers is being triggered on an upsert.
Here is what I am trying to do in a nutshell.
My meteor js app boots and then connects to an endpoint, fetching data and then upserting it into the collection.
collection.update({'sys.id': item.sys.id}, item, {upsert: true});
The 'sys.id' selector checks to see if the item exists, and then updates if it does or adds if it does not.
I have an observer monitoring the above collection, which then acts when an item has been added/updated to the collection.
collection.find({}).observeChanges({
added: this.itemAdded.bind(this),
changed: this.itemChanged.bind(this),
removed: this.itemRemoved.bind(this)
});
The first thing that puzzles me is that when the app is closed and then booted again, the 'added()' callback is fired when the collection is observed. What I would hope to happen is that the changed() callback is fired.
Going back to my original update - is it possible in Mongo to conditionally update something, so you have the selector, then the item, but only perform the update when another condition is met?
// Incoming item
var item = {
sys: {
id: 1,
revision: 5
}
};
collection.update({'sys.id': item.sys.id, 'sys.revision': {$gt: item.sys.revision}, item, {upsert: true});
If you look at the above code, what this is going to do is try to match the sys.id which is fine, but then the revisions will of course be different which means the update function will see it as a different document and then perform a new insert, thus creating duplicate data.
How do I fix this?
To your main question:
What you want is called findAndModify. First, look for the the document meeting the specs, and then update accordingly. This is a really powerful idea because if you did it in 2 queries, the document you found could be deleted/updated before you got to update it. Luckily for you, someone made a package (I really wish this existed a year ago!) https://github.com/fongandrew/meteor-find-and-modify
If you were to do this without using findAndModify you'd have to use javascript to find the doc, see if it matches your criteria, and then update it. In your use case, this would probably work, but there will always be that "what if" in the back of your mind.
Regarding observeChanges, the added is called each time the local minimongo receives a document (it's just reading what the DDP is telling it). Since a refresh will delete your local collection, you have to add those docs one by one. What you could do is wait until all added callbacks have fired, and then run your server method. In doing so, you get a ton of adds, and then a couple more changes will trickle in afterwards.
As Matt K said, you want findAndModify. There are some gotchas to be aware of:
findAndModify is about 100x slower than a find followed by an update. Find+modify is, obviously, not atomic and so won't do what you need, but be aware of the speed hit. (This is based off experience with MongoDB v2.4, so run some benchmarks to confirm under your own version.)
If your query matches multiple items, findAndModify will only act on the first one. In this case, you're querying on a unique id, but be aware of the issue for future use.
findAndModify will return the document after doing its thing, but by default it returns the pre-modification version. If you want the modified one, you need to pass the 'new: true' in your query.