Create mongo change stream in the mongo shell - mongodb

MongoDB introduced change streams in their 3.6 release.
I wanted to implement mongo change stream in my code and wanted to understand how it works. I will implement using the java driver and it's pretty clear.
But I wanted to know if there is there any way to open a change stream on in the mongo shell? Couldn't find much resources on that.

The db.collection.watch command opens a change stream cursor.
For example:
watchCursor = db.getSiblingDB("data").sensors.watch(
[
{ $match : {"operationType" : "insert" } }
]
)
while (!watchCursor.isExhausted()){
if (watchCursor.hasNext()){
print(tojson(watchCursor.next()));
}
}
Plenty more detail in the docs.

Related

MongoDB - Execute a command conditionally

I need to execute a command that is part of my migration scripts (mongock java library) conditionally based on Mongo version
In case Mongo version is lower then 4.2 I need to execute this command. For Mongo 4.2 and higher it should not be executed.
db.getSiblingDB('admin').runCommand( { setParameter: 1, failIndexKeyTooLong: false } )
Is there a way how to do it?
Thank you,
Lukas
don't know if you already found a solution for this.
The idea is to figure out the Mongo's version inside the changeSet and then perform the required actions.
I will assume you are using the last Mongock's release for version 3.x.x, which is 3.3.2 or 4.0.x.alpha, so you should use MongockTemplate, instead of MongoTemplate. Don't worry, it's just a wrapper/decorator, you won't miss anything from the original API.
So you can do something like this:
#ChangeSet(id = "changeset-1", order = "001", author = "mongock")
public void changeSet(MongockTemplate mongockTemplate, ClientRepository clientRepository) {
String version = mongockTemplate.executeCommand(new Document("buildinfo", new BsonString("")))
.get("version")
.toString();
if(getNumericalVersion(version) < 42) {
//do your actions
} else {
//do you other actions
}
}
NOTE 1: We don't recommend using executeCommand. In this case, for taking the version it's fine, but in general we recommend not using it, specially for writes.
NOTE 2: Currently we are working on version 4, which will allow to scan multiple packages and even isolated ChangeLog classes. So another approach would be to take the version in the bean creation and inject the change or not depending on the MongoDB's version

How to manually update a mongodb collection from the command line in cloud9-ide?

I'm in a meteor/mongodb environment and I'm trying to add a key/value to the users collection and check that the updated data now exists on the client.
In the cloud9 ide, on the command line, I enter
db.users.find({emails : { $elemMatch : { "address":"colm#1.com" }}});
This finds the corresponding entry.
Then,in cloud9 ide, I do
db.users.findAndModify({ query:{emails : { $elemMatch : { "address":"colm#1.com" }}}, update:{$set:{ "roles":"VIP"}}});
This works to the extent that when I repeat the db.user.find.. command above I now see the "roles":"VIP" at the same level as the "emails" key.
I restart the server and login to the website as colm#1.com.
In the console on the browser I type in
Meteor.user().emails[0].address and it replies colm#1.com
However when I type in
Meteor.user().roles it tells me undefined.
it looks as though the db change I make on the console in cloud9-ide, doesn't get propagated to the client ? Is this normal, or what am I doing wrong ?
P.S. I'm also confused by the existence of local and meteor databases. I believe that I am in meteor db by default but I'm not entirely sure about this.
best regards / Colm

Meteor.subscribe on server side

I want to create a backend service which monitors a mongodb collection for new entries. As those are being created, I wish to run processing and update them.
I thought doing so with a Meteor service/app would be a wise idea because Meteor uses 'oplog tailing' which seems ideal for this purpose (I'd rather avoid polling if possible).
As such, I figured creating a minimal server-side-only app should solve it.
So basically, I need something along these lines:
if (Meteor.isServer) {
MyCollection = new Mongo.Collection('myCollection');
Meteor.publish('myCollectionPub', function () {
return MyCollection.find({ some: criteria... });
}
// is there such a thing?
Meteor.serverSideSubscribe('MyCollectionPub',
function (newDocs) {
// process/update newDocs
});
}
According to the Meteor docs, I cannot use Meteor.subscribe() on the server (and indeed it crashes if I try).
Question is:
Are there ways of 'subscribing' to collection updates on the server?
The PeerLibrary server-autorun package (along with it's dependant, reactive-mongo) will provide you with easy server-side observation of collections.
An alternative to #tarmes suggestion is the collection-hooks package, however as pointed out by David Weldon, it will only trigger in instance it is run in:
https://github.com/matb33/meteor-collection-hooks
MyCollection.after.insert(function (userId, doc) {
// ...
});
If you need it to run even when another instance makes a change in the mongo database, you can observe a cursor that is returned from your collection:
MyCollection.find({created_at : {$gt: some_current_time}}).observe({
added: function(item) {
// Alert code
}
});

Mongodb C# how do I set newCollectionsUsePowerOf2Sizes=false;

I am creating a large number of documents and collections and would like to set newCollectionsUsePowerOf2Sizes=false
What is the C# code to set this property.
thanks
I haven't tried this with C# but in mongoshell we can do this:-
db.runCommand( {collMod: "products", usePowerOf2Sizes : true })
This same command can be send using java driver using this function in DB api (link):-
public CommandResult command(DBObject cmd)
You can find a C# equivalent of this. Hope this helps.

Full-text search with Meteor.js and MongoDB

I am experimenting with Meteor.js and looking for a full-text search engine that can run on Meteor/MongoDB server. It seems that Meteor has not developed this feature.
I wonder if there is an existing solution for adding full-text search to Meteor app.
The only thing I can find is MongoLantern, which has node.js API. How should I go about adding MongoLantern to my Meteor app?
MongoDB 2.4 will have a full text search in it. Guide can be found here.
If you are prepared to run the development releases you can download MongoDB 2.3 now - it contains text search.
Update: MongoDB 2.4 has been released. Text search is described as Beta.
The guide for text search is here and the mongod must be run like this
mongod --setParameter textSearchEnabled=true
Take a look at http://lunrjs.com/. That might also help in getting the near-instant performance of real Meteor app.
You might want to have a look at:
https://github.com/Crenshinibon/spomet
It's a Meteor native package to provide full-text search. It has an easy to include search-box with autocompletion.
You can read a tutorial about an extended example application here:
http://shiggyenterprises.wordpress.com/2013/09/28/developing-a-full-text-search-enabled-meteor-app/
There is also another way to implement a solution with Meteor. It's Search Source.
It's a kind of typeahead but without the UI part. It exposes a reactive datasource where you can use it to build the UI with Blaze as you need.
Here's a demo app: https://instant-search-demo.meteor.com/
Above app is an instant search app to search Meteor packages. How it can build with search source is documented in this article
In brief this is how search source works:
In client, create a source
var options = {
keepHistory: 1000 * 60 * 5,
localSearch: true
};
var fields = ['packageName', 'description'];
PackageSearch = new SearchSource('packages', fields, options);
Then in the server define the search source
SearchSource.defineSource('packages', function(searchText, options) {
var options = {sort: {isoScore: -1}, limit: 20};
if(searchText) {
var regExp = buildRegExp(searchText);
var selector = {packageName: regExp, description: regExp};
return Packages.find(selector, options).fetch();
} else {
return Packages.find({}, options).fetch();
}
});
function buildRegExp(searchText) {
// this is dumb implementation
var parts = searchText.trim().split(' ');
return new RegExp("(" + parts.join('|') + ")", "ig");
}
Now get the data source and render it
Template.searchResult.helpers({
getPackages: function() {
return PackageSearch.getData({
transform: function(matchText, regExp) {
return matchText.replace(regExp, "<b>$&</b>")
},
sort: {isoScore: -1}
});
}
});
Finally do the search
PackageSearch.search("the text to search");
You can learn more about how each of the above works with from the documentation.