there are some questions here regarding how to save a result from a query into a javascript varialbe, but I'm just not able to implement them. The point is that I have a much difficult query, so this question is, in my opinion, unique.
Here is the problem. I have a collection namend "drives" and a key named "driveDate". I need to save 1 variable with the smallest date, and other with the biggest date.
The query for the smallest date is:
> db.drives.find({},{"_id":0,"driveDate":1}).sort({"driveDate":1}).limit(1)
The result is:
{ "driveDate" : ISODate("2012-01-11T17:24:12.676Z") }
how dan I save this to a variable, can I do something like:
tmp = db.drives.find({},{"_id":0,"driveDate":1}).sort({"driveDate":1}).limit(1)
Thanks!!!
Assuming you're trying to do this in the shell:
tmp = db.drives.find({}, {_id:0, driveDate:1}).sort({driveDate:1}).limit(1).toArray()[0]
find returns a cursor that you need to iterate over to retrieve the actual documents. Calling toArray on the cursor converts it to an array of docs.
After some time figuring out, I got the solution. here it is, for future reference:
var cursor = db.drives.find({},{"_id":1}).sort({"driveDate":1}).limit(1)
Then I can get the document from the cursor like this
var myDate = cursor.next()
That's it. Thanks for your help
Related
I'm using mongo's findOneAndReplace() with upsert = true and returnNewDocument = true
as basically a way to not insert duplicate. But I want to get the _id of the new inserted document (or the old existing document) to be passed to a background processing task.
BUT I also want to log if the document was Added-As-New or if a Replacement took place.
I can't see any way to use findOneAndReplace() with these parameters and answer that question.
The only think I can think of is to find, and insert in two different requests which seems a bit counter-productive.
ps. I'm actually using pymongo's find_one_and_replace() but it seems identical to the JS mongo function.
EDIT: edited for clarification.
Is it not possible to use replace_one function ? In java I am able to use repalceOne which returns UpdateResult. That has method for finding if documented updated or not. I see repalce_one in pymongo and it should behave same. Here is doc PyMongo Doc Look for replace_one
The way I'm going to implement it for now (in python):
import pymongo
def find_one_and_replace_log(collection, find_query,
document_data,
log={}):
''' behaves like find_one_or_replace(upsert=True,
return_document=pymongo.ReturnDocument.AFTER)
'''
is_new = False
document = collection.find_one(find_query)
if not document:
# document didn't exist
# log as NEW
is_new = True
new_or_replaced_document = collection.find_one_and_replace(
find_query,
document_data,
upsert=True,
return_document=pymongo.ReturnDocument.AFTER
)
log['new_document'] = is_new
return new_or_replaced_document
This Meteor code needs to check if a certain document exist in the collection by checking if a cursor is returned, and if no cursor returned then the document does not exist. but it always returns true even if there is no value "alosh" for the text field in any of the documents in the collection
.
Why and how can it be fixed? Thanks
if (myCollection.find({text: 'alosh'}, {limit: 1})) {console.log('found');}
edit
The reason I did not use colllection.findOne is my understanding that it is much slower according to this post
Idea for solution:
You want to understand if there is a document with a certain value for a certain property. You could use:
if(myCollection.findOne({text: 'alosh'})){
console.log("found");}
Add a count. A cursor is always going to be a truthy value as the cursor itself is returned. You need to check the records contained in the cursor so...
if (myCollection.find({text: 'alosh'}, {limit: 1}).count()) {
console.log('found');
}
Because no docs returned is 0 and 0 is falsey this should only return when documents are found
Mongo cursors seem to behave the same as arrays in that an empty cursor (and an empty array) evaluate to true.
So !![] //true and !!collection.find({text : "alosh"}) //true.
BUT collection.findOne({text : "alosh"}) will fail your if - so use that instead
http://docs.meteor.com/#/full/findone
I know this has been asked before, but I have yet to find a solution that works efficiently. I am working with the MongoDB C# driver, though this is more of a general question about MongoDB operations.
I have a document structure that looks something like this:
field1: value1
field2: value2
...
users: [ {...user 1 subdocument...}, {...user 2 subdocument...}, ... ]
Some facts:
Each user subdocument includes further sub-arrays & subdocuments (so they're fairly complex).
The average users array only contains about 5 elements, but in the worst case can surpass 100.
Several thousand update operations on multiple users may be conducted per day in this system, each on one document at a time. Larger arrays will receive more frequent updates due to their data size.
I am trying to figure out how to do this efficiently. From what I've heard, you cannot directly set several array elements to new values all at once, so I had to try something else.
I tried using the $pullAll / $AddToSet + $each operations to remove the old array and replace it with a modified one. I am aware that $pullall can remove only the elements that I need as well, but I would like to preserve the order of elements.
The C# code:
try
{
WriteConcernResult wcr = collection.Update(query,
Update.Combine(Update.PullAll("users"),
Update.AddToSetEach("users", newUsers.ToArray())));
}
catch (WriteConcernException wce)
{
return wce.Message;
}
In this case newUsers is aList<BsonValue>converted to an array. However I am getting the following exception message:
Cannot update 'users' and 'users' at the same time
By the looks of it, I can't have two update statements in use on the same field in the same write operation.
I also tried Update.Set("users", newUsers.ToArray()), but apparently the Set statement doesn't work with arrays, just basic values:
Argument 2: cannot convert from 'MongoDB.Bson.BsonValue[]' to 'MongoDB.Bson.BsonValue'
So then I tried converting that array to a BsonDocument:
Update.Set("users", newUsers.ToArray().ToBsonDocument());
And got this:
An Array value cannot be written to the root level of a BSON document.
I could try replacing the whole document, but that seems like overkill and definitely not very efficient.
So the only thing I can think of now is to run two separate write operations: one to remove the unwanted old users and another to replace them with their newer versions:
WriteConcernResult wcr = collection.Update(query, Update.PullAll("users"));
WriteConcernResult wcr = collection.Update(query, Update.AddToSetEach("users", newUsers.ToArray()));
Is this my best option? Or is there another, better way of doing this?
Your code should work with a minor change:
Update.Set("users", new BsonArray(newUsers));
BsonArray is a BsonValue, where as an array of documents is not and we don't implicitly convert arrays like we do other primitive values.
this extension method solve my problem:
public static class MongoExtension
{
public static BsonArray ToBsonArray(this IEnumerable list)
{
var array = new BsonArray();
foreach (var item in list)
array.Add((BsonValue) item);
return array;
}
}
Mongo has a nice feature that tells you when a document was created.
ObjectId("53027f0adb97425bbd0cce39").getTimestamp() = ISODate("2014-02-17T21:28:42Z")
How would I get about finding all documents that were created before lets say February 10th 2014? Searched around but doesn't seem like this question comes up. Any help is appreciated! Thanks!
You mean something like this?
db.YOUR_COLLECTION.find({YOUR_DATE_FIELD: { "$lt": ISODate("2014-02-10") }})
Guess that you have to make the same as JoJo recommended:
Convert a date to an ObjectId
Filter ID using $lt and returned ObjectId
Using pymongo you can do something like this:
gen_time = datetime.datetime(2014, 2, 10)
dummy_id = ObjectId.from_datetime(gen_time)
result = collection.find({"_id": {"$lt": dummy_id}})
Reference: http://api.mongodb.org/python/1.7/api/pymongo/objectid.html
I have been trying to work out what is the best way to search for gather all of the documents in a database that have a certain date.
Originally I was trying to use FTsearch or search to move through a document collection, but I changed over to processing a view and associated documents.
My first question is what is the easiest way to spin through a set of documents and find if a date stored in the documents is greater than or less than a specified date?
So, to continue working I implemented the following code.
If (doc.creationDate(0) > cdat(parm1))
And (doc.creationDate(0) < CDat(parm2)) then
...
end if
but the results are off
Included! Date:3/12/10 11:07:08 P1:3/1/10 P2: 3/5/10
Included! Date:3/13/10 9:15:09 P1:3/1/10 P2: 3/5/10
Included! Date:3/17/10 16:22:07P1:3/1/10 P2: 3/5/10
You can see that the date stored in the doc is not between P1 and P2. BUT! it does limit the documents with a date less than P1 correctly. So I won't get a result for a document with a date less than 3/1/10
If there isn't a better way than the if statement, can someone help me understand why the two examples from above are included?
Hi you can try something like this:
searchStr = {(Form = "yourForm" & ((#Created > [} & parm1 & {]) & (#Created < [} & parm2 & {])))}
Set docCollection = currentDB.Search(searchStr, Nothing, 0)
If(docCollection.Count > 0)Then
'do your stuff with the collection returned
End If
Carlos' response is pretty good.
If you have a lot of documents, you can also use a full-text search which will is much faster. The method call is very similar (db.ftsearch(), online help can be found here).
The standard DB Search method operates in the same way as view index updates, so it can get a little slow if you have thousands of documents to search through.
Just make sure you enable full text index for your database in the database properties, (last tab).
Syntax on this approach is very similar, this link provides a good reference for FTsearch. Using Carlos' syntax, you can substitute FTSearch and searchStr assignment for faster searching.