I am currently working on a mongoDB database for a class project. However, I'm very new to it.
I must find all documents where the latitude is greater than a certain value: 39. Longitude value can be anything.
Please find below the example of one document, showing the global structure of the database.
Example
Looking at MongoDB's documentation, I have two hints:
Trying a nested document query ("end station location.coordinates.0:{$gt:39})
Yet, it is not working..
Trying some geometric intersection. As I'm very new to MongoDB, I don't know if it'd be the easiest way to find what's I'm looking for.
Could someone help me improving myself ?
Regards,
I think your problem is you are looking for values greater than 39 in the first position in the array. And these values in your example are negative numbers, so no one is grater than 39.
If you do the same query using $lt you will get results. Example here.
Also, to find values $gt: 39 you have to find the second position into the array:
db.collection.find({
"end station location.coordinates.1": {
"$gt": 39
}
})
Example here
Also, if you want to get the values if exists almost in one filed end station location or start station location you need $or operator like this:
db.collection.find({
"$or": [
{
"end station location.coordinates.1": {
"$gt": 39
}
},
{
"start station location.coordinates.1": {
"$gt": 39
}
}
]
})
Example here
And remember, you want to search by second position into the array, so you have to use coordinates.1.
I am trying to mimic the functionality of the right sidebar of this example for my Angular site.
I don't know what this is called, or even how to go about it on the front end or back end!
My assumption:
Create a form with values coming straight from the DB and only show the desired parameter (i.e. db.collection.find(query, {parameter: 1}) which will be called to update each time a user modifies the form. Additionally, the results would also be updated on selection (I have over 100MB of documents, returning ALL of them would be troublesome, how can I limit the number of documents returned to let's say 20 or 50 (user input?) and paginate it (1000 documents returned / 50 per page = 20 'pages')
Each input that is selected, a { 'field' : value } would be returned -- but I am not sure how to control an empty value (i.e. what if a user doesn't pick a fuel type or transmission range?)
How do I go about designing such a feature correctly?
1) In your query, use limit statement:
var options = { "limit": 20 }
collection.find({}, options).toArray(...);
2) you can validate user empty input (for eg. with express-validator):
req.checkBody('postparam', 'Invalid postparam').notEmpty()
req.getValidationResult().then(function(result) {
if (!result.isEmpty()) {
res.status(400).send('There have been validation errors: ' + util.inspect(result.array()));
return;
}
and based on result choose default value/pass error/render ask page for user
I am using a MongoDB for a new app I am creating and I only need certain data from it. I require the following fields: current (boolean), position, sector, and name. The position field is populated with one of four values - "cash, SPVR, OFF, and training", while the sector field has one of two values - "Break or Working". I want a query that will give me all records where the following conditions exist:
1. current = TRUE
2. Position = "SPVR" or "CASH" OR Sector = "BREAK" and
3. Name is not NULL
The problem I have is that there are hundreds of records that have a value of BREAK, but most of them do not have a value in the Name field. I don't want any records that do not have a name associated with them. So in that respect, in line 2 above, I'm guessing the OR could be AND?
This is mu current start at the Mongoid statement
get '/currentstate*' do
StateTransaction.where( current: true, :position.in =>["SPVR", "CASH"] ).to_json
end
Any help would be greatly appreciated.
Thanks!!
It should work
StateTransaction.where(current: true, :name.ne => ["",nil]).and(
StateTransaction.or(
{:position.in =>["SPVR", "CASH"]},
{sector: "BREAK"}
).selector
)
Following is arguably simpler:
sts = StateTransaction.where(current: true, :name.ne => ["",nil])
sts.any_of(:position.in => ["SPVR", "CASH"], sector: 'BREAK')
I'm trying to create an android app which pulls first 1-10 documents in the mongodb collection and show those item in a list, then later when the list reaches the end i want to pull 11-20 documents in the mongodb collection and it goes on.
def get_all_tips(from_item, max_items):
db = client.MongoTip
tips_list = db.tips.find().sort([['_id', -1]]).limit(max_items).skip(from_item)
if tips_list.count() > 0:
from bson import json_util
return json_util.dumps(tips_list, default=json_util.default), response_ok
else:
return "Please move along nothing to see here", response_invalid
pass
But the above code does not work the way i intended but rather it returns from from_item to max_items
Example: calling get_all_tips(3,4)
It returns:
Document 3, Document 4, Document 5, Document 6
I'm expecting:
Document 3, Document 4
In your code you are specifying two parameters.
from_item: which is the starting index of the documents to return
max_items: number of items to return
Therefore calling get_all_tips(3,4) will return 4 documents starting from document 3 which is exactly what's happening.
Proposed fixes:
If you want it to return documents 3 and 4 call get_all_tips(3,2) instead, which means return a maximum of two documents starting from 3.
If you'd rather like to specify the start and end indexes in your function, I recommend the following changes:
def get_all_tips(from_item, to_item):
if to_item < from_item:
return "to_item must be greater than from item", bad_request
db = client.MongoTip
tips_list = db.tips.find().sort([['_id', -1]]).limit(to_item - from_item).skip(from_item)
That being said, I'd like to point out that MongoDb documentation does not recommend use of skip for pagination for large collections.
MongoDb 3.2 cursor.skip
I'm trying to use the sort feature when querying my mongoDB, but it is failing. The same query works in the MongoDB console but not here. Code is as follows:
import pymongo
from pymongo import Connection
connection = Connection()
db = connection.myDB
print db.posts.count()
for post in db.posts.find({}, {'entities.user_mentions.screen_name':1}).sort({u'entities.user_mentions.screen_name':1}):
print post
The error I get is as follows:
Traceback (most recent call last):
File "find_ow.py", line 7, in <module>
for post in db.posts.find({}, {'entities.user_mentions.screen_name':1}).sort({'entities.user_mentions.screen_name':1},1):
File "/Library/Python/2.6/site-packages/pymongo-2.0.1-py2.6-macosx-10.6-universal.egg/pymongo/cursor.py", line 430, in sort
File "/Library/Python/2.6/site-packages/pymongo-2.0.1-py2.6-macosx-10.6-universal.egg/pymongo/helpers.py", line 67, in _index_document
TypeError: first item in each key pair must be a string
I found a link elsewhere that says I need to place a 'u' infront of the key if using pymongo, but that didn't work either. Anyone else get this to work or is this a bug.
.sort(), in pymongo, takes key and direction as parameters.
So if you want to sort by, let's say, id then you should .sort("_id", 1)
For multiple fields:
.sort([("field1", pymongo.ASCENDING), ("field2", pymongo.DESCENDING)])
You can try this:
db.Account.find().sort("UserName")
db.Account.find().sort("UserName",pymongo.ASCENDING)
db.Account.find().sort("UserName",pymongo.DESCENDING)
This also works:
db.Account.find().sort('UserName', -1)
db.Account.find().sort('UserName', 1)
I'm using this in my code, please comment if i'm doing something wrong here, thanks.
Why python uses list of tuples instead dict?
In python, you cannot guarantee that the dictionary will be interpreted in the order you declared.
So, in mongo shell you could do .sort({'field1':1,'field2':1}) and the interpreter would sort field1 at first level and field 2 at second level.
If this syntax was used in python, there is a chance of sorting by field2 at first level. With tuple, there is no such risk.
.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])
Sort by _id descending:
collection.find(filter={"keyword": keyword}, sort=[( "_id", -1 )])
Sort by _id ascending:
collection.find(filter={"keyword": keyword}, sort=[( "_id", 1 )])
DESC & ASC :
import pymongo
client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["mydatabase"]
col = db["customers"]
doc = col.find().sort("name", -1) #
for x in doc:
print(x)
###################
import pymongo
client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["mydatabase"]
col = db["customers"]
doc = col.find().sort("name", 1) #
for x in doc:
print(x)
TLDR: Aggregation pipeline is faster as compared to conventional .find().sort().
Now moving to the real explanation. There are two ways to perform sorting operations in MongoDB:
Using .find() and .sort().
Or using the aggregation pipeline.
As suggested by many .find().sort() is the simplest way to perform the sorting.
.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])
However, this is a slow process compared to the aggregation pipeline.
Coming to the aggregation pipeline method. The steps to implement simple aggregation pipeline intended for sorting are:
$match (optional step)
$sort
NOTE: In my experience, the aggregation pipeline works a bit faster than the .find().sort() method.
Here's an example of the aggregation pipeline.
db.collection_name.aggregate([{
"$match": {
# your query - optional step
}
},
{
"$sort": {
"field_1": pymongo.ASCENDING,
"field_2": pymongo.DESCENDING,
....
}
}])
Try this method yourself, compare the speed and let me know about this in the comments.
Edit: Do not forget to use allowDiskUse=True while sorting on multiple fields otherwise it will throw an error.
.sort([("field1",pymongo.ASCENDING), ("field2",pymongo.DESCENDING)])
Python uses key,direction. You can use the above way.
So in your case you can do this
for post in db.posts.find().sort('entities.user_mentions.screen_name',pymongo.ASCENDING):
print post
Say, you want to sort by 'created_on' field, then you can do like this,
.sort('{}'.format('created_on'), 1 if sort_type == 'asc' else -1)