I am wondering if it is possible to use a mongodb geospatial index with Meteor architecture.
Minimongo does not implement geospatial indices, but does this mean that we cannot use this mongo feature on the server side?
For example, with the todos app, if we use location on the todo, will it be possible to do:
// Publish complete set of lists to all clients.
Meteor.publish('todos', function (lon,lat) {
return Todos.find({loc: {$near:[lon,lat]}}).limit(2);
});
And on the client side :
Meteor.subscribe('todos', lon, lat );
Yes, you can use the MongoDB geospatial index within Meteor, and you can create that index from within your Meteor app too.
- Geospatial Search
I'm using the $within operator below, as opposed to the $near operator mentioned above, but this still applies:
Meteor.publish('places', function(box) {
return Places.find({ loc : { $within : { $box : box }}});
});
Reminder: These kinds of geo queries are only available on the server (currently).
- Creating a Geospatial Index from within Meteor (rather than in a MongoDB shell)
Places._ensureIndex({ loc : "2d" });
e.g. You could use the above in your bootstrap.js.
Also, you'll probably want to put your ensureIndex in Meteor.startup, or perhaps when you're inserting some initial data.
Warning: As mentioned here, the above method of calling ensureIndex is a work around for want of an official way to call it, so please expect that this might change.
Update: now reflects changes in Meteor 0.5.0, see #Dror's comment below.
Yes, I think you can.
On the server side, Meteor delegates find/update/.. into node-mongo-native call. You can take a look the code in packages/mongo-livedata/mongo_driver.js. And as I know, node-mongo-native supports geospatial index.
Related
I was going through the documentation on the official site, where I happened to find out the term query-shape while browsing details over the indexes section.
The details look interesting and quite possibly a list of these could help me with all possible queries that are being raised to a cluster while I am planning to onboard an existing deployed application.
But the question that I have now is that is there a way to do the above on the command line for a collection(or complete database)?
As a side note, I use both compass community and robo3t as tools built over CLI to access the datastore and as well comfortable to run the command on mongo shell directly too.
With some more time and effort, I could find PlanCache.listQueryShapes which was a slight variation towards the more recent version of mongo which I was using.
Seemingly the $planCacheStats introduced in 4.2 was something I was looking forward to. The following query helped me list all the query shapes over a collection as mentioned in the list query shapes section.
db.user_collections.aggregate( [ { $planCacheStats: { } } ,
{ $project: {createdFromQuery: 1, queryHash: 1 } } ] )
I am using MongoClient on a NodeJS service.
As part of improving my service's performance I want to determine if I should act differently when handling with single id vs with multiple ids in the terms of querying Mongo.
My current code looks like this:
collection.find({ id: {$in: ids } })
I wanted to know if I would split the code to handle single id separately would make the performance any better, somewhat like this:
if ids.count == 1
collection.findOne({ id: ids.first })
else
collection.find({ id: {$in: ids } })
end
According with MongoDB Driver for NodeJS, findOne is deprecated in favour of find().
Deprecated, use find().limit(1).next(function(err, doc){}) instead
http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findOne
Even more, findOne() is syntax sugar of find().limit(1).toArray()
I strongly suggest you to take a look if something is deprecated before use it in production at that link
I easily can store geolocation Data into MongoDB with an Eve RESTful API Server running.
So I store data like:
loc : {
lng: 13.01111,
lat: 51.01111
}
Validation etc. works nicely.
But: I was unable to find a way to get geolocation data out of the REST API.
There are sample queries over there working fine at the command-line, but there seems to be no way to query the API a appropriate way.
Is there a way to throw MongoDB like Queries against the REST API or
which is the prefered way to customize the API for such a purpose.
To make things clear: There is already a 2d index and geoWithin queriey at the mongo-cmd are working fine.
It's just about how to query via the REST API.
It's not mentioned but it should be supported. I'm not into geo stuff but I just tried to issue a $near query and it returned an operation failure because my database was missing the necessary 2dindex. This means that the command was correctly passed to the database.
If you are using a rest client like Postman the syntax should be something like this (I'm using $near for simplicity):
?where={"loc": {"$near": {"$geometry":{"type": "Point", "coordinates": [13,51]}}, "$maxDistance": 100}}
If you are using app.get method remember to json.loads your query. Hope this helps.
Points in MongoDB can be stored as either GeoJSON Point Objects,
loc : {
type: 'Point',
coordinates: [13.0111, 51.0111]
};
or legacy coordinate pairs.
loc : [13.01111, 51.01111]
The collection should have an index (either 2dsphere or 2d, respectively) to handle queries efficiently.
I'm pretty sure EVE has a built-in geoWithin operator. It's just not working because you're querying an invalid location format.
I have trouble understanding when exactly the database is hit when using node-mongodb-native. Couldn't find any reference on that. As everything is callback based, it gave me the feeling that every single call hits the database ... For example, are those two snippets any different in terms of how many times the database is hit :
// ---- 1
db.collection('bla', function(err, coll) {
coll.findOne({'blo': 'bli'}, function(err, doc) {
coll.count(function(err, count) {
console.log(doc, count)
})
})
})
// ---- 2
db.collection('bla', function(err, coll) {
coll.findOne({'blo': 'bli'}, function(err, doc) {
db.collection('bla', function(err, coll) {
coll.count(function(err, count) {
console.log(doc, count)
})
})
})
})
I was basically wondering whether I can cache instances of collections and cursors. For example, why not fetch the collections I need only once, at server start, and reuse the same instances indefinitely ?
I'd really like to understand how the whole thing work, so I'd really appreciate a good link explaining stuff in details.
Looking at the source code for the node.js driver for collection it seems it will not ping MongoDB upon creation of the collection unless you have strict mode on: https://github.com/mongodb/node-mongodb-native/blob/master/Readme.md#strict-mode
The source code I looked at ( https://github.com/mongodb/node-mongodb-native/blob/master/lib/mongodb/db.js#L446 ) reinforced the idea that if strict was not on then it would just try and create a new node.js collection object and run the callback.
However findOne and count will break the "lazy" querying of node.js and will force it to query the database in order to get results.
Note: The count being on the collection won't enforce a "true" count of all items in the collection. Instead it will garnish this information from the collection meta.
So for the first snippet you should see two queries run. One for the findOne and one for the count and two for the second snippet as well since creating the collection after the findOne should not enforce a query to MongoDB.
After some googling, I have find this link about best practices for node-mongodb-native. It is answered by Christian Kvalheim who seem to be the maintainer of the library. He says :
"You can safely store the collection objects if you wish and reuse them"
So even if the call to collection might hit the database in case it is made in strict mode, the actual client-side collection instance can be reused.
Can I write a procedure from server side which later on gets stored in Db and used for further transactions.
If yes can you provide me a sample code which shows how to write the js from server side in java.
Can I write a procedure from server side which later on gets stored in Db and used for further transactions.
No but as #Philipp states you can write a block of JavaScript which will be evaled within the bult in JavaScript engine in MongoDB (spidermonkey atm unles you compile with V8).
I should be clear this IS NOT A STORED PROCEDURE AND IT DOES NOT RUN "SERVER SIDE" as SQL procedures do.
You must also note that the JS engine is single threaded and eval (when used) locks, and about a tonne of other problems.
Really the whole ability to store functions in the system collection is to store repeating code for tasks such as MR.
It is possible to do that, but 10gen advises that you shouldn't do it. Javascript functions can be stored in the special collections system.js and invoced through the eval command.
The rest of this post is copy&pasted from the official documentation: http://www.mongodb.org/display/DOCS/Server-side+Code+Execution#Server-sideCodeExecution-Storingfunctionsserverside
Note: we recommend not using server-side stored functions when possible. As these are code it is likely best to store them with the rest of your code in a version control system.
There is a special system collection called system.js that can store JavaScript functions to be reused. To store a function, you would do:
db.system.js.save( { _id : "foo" , value : function( x , y ){ return x + y; } } );
_id is the name of the function, and is unique per database.
Once you do that, you can use foo from any JavaScript context (db.eval, $where, map/reduce)
Here is an example from the shell:
> db.system.js.save({ "_id" : "echo", "value" : function(x){return x;} })
> db.eval("echo('test')")
test
See http://github.com/mongodb/mongo/tree/master/jstests/storefunc.js for a full example.
In MongoDB 2.1 you will also be able to load all the scripts saved in db.system.js into the shell using db.loadServerScripts()
>db.loadServerScripts()
>echo(3)
3
Well you can use morphia. It is an ODM for mongo in Java. I know it is not like a PL/SQL kind of solution which you exactly want. But mongo has no extensive support for constraints or triggers as in Oracle or SQL Server. Validations and stuff needs to be done through code. ODM's like Morphia in Java, Mongoose in Node.js or Mongoengine in Python are pretty decent emerging libraries you can use for such tasks, but these constraints are on app side.