I'm running this code in a mongodb console:
var participantsWithoutCategory = db.participant.find({eventId: ObjectId("536d5564e7b237df30b628cc"), category: {$exists: false}});
var event = db.event.find({_id: ObjectId("536556c4eaa237df30b628cc")});
participantsWithoutCategory.forEach(function (entry) {
var userId = new ObjectId("" + entry._id + "");
var user = db.user.find( { _id: userId} );
print("got user: " + user);
});
and the result of the prints is:
got user: DBQuery: Oc5mjdKkhyDb3r6rhnzw.user -> { "_id" : ObjectId("536d8586ebb237df30b62bcb") }
so I'm just wondering how to get the actual object rather than a pointer to it?
if I try to get any of its properties such as user.dob I get a null :(
Turns out that's how mongo says that the query had no results... I've fixed it by using the right property of the object and not the _id but that's beyond the point.
The interesting thing here is that mongo gives back the DBQuery when find() returns nothing.
Related
How can I tell when findOneAndUpdate successfully updates a document? huh variable always returns the same thing (whether id is in the database or not) and doc is always null.
var query = {id : id };
var huh = schemaModel.findOneAndUpdate(query, obj, function(doc) {
console.log(doc);
if(doc) {
callback(doc);
} else {
errback('');
}
}
);
console.log(huh);
You are only passing one parameter to the callback in your findOneAndUpdate query.
I think that your query succeeds, but doc will always come null when you successfully update the object as it is the first parameter which is the err.
Also, I do not see the code for your callback function, so I am just presuming that it can be accessed in the scope of your function.
var query = {id : id };
var huh = schemaModel.findOneAndUpdate(query, obj, function(err, doc) {
if(err) {
return "Error spotted!";
} else {
return "Found & Updated";
}
}
);
console.log(huh);
By returning those values, you are basically assigning them to the huh variable and it should log accordingly. It serves as a logging mechanism.
I have the following Document:
{
"_id": 100,
"Version": 1,
"Data": "Hello"
}
I have a function which return a number from a sequence:
function getNextSequence(name) {
var ret = db.Counter.findAndModify(
{
query: { _id: name },
update: { $inc: { value: 1 } },
new: true,
upsert: true
}
);
return ret.value;
}
I can use this for optimistic concurrency by performing the following Mongo command:
db.CollectionName.findAndModify({
query: { "_id" : NumberLong(100), "Version" : 1 },
update: { "$set" : {
"Data": "Here is new data!",
"Version" : db.eval('getNextSequence("CollectionName")') }
},
new: true
}
);
This will update the document (as the _id and Version) match, with the new Data field, and also the new number out of the eval call.
It also returns a modified document, from which I can retrieve the new Version value if I want to make another update later (in the same 'session').
My problem is:
You cannot create an Update document using the MongoDB C# client that will serialize to this command.
I used:
var update = Update.Combine(
new UpdateDocument("$set", doc),
Update.Set(versionMap.ElementName, new BsonJavaScript("db.eval('getNextSequence(\"Version:CollectionName\")')")))
);
If you use what I first expected to perform this task, BsonJavascript, you get the following document, which incorrectly sets Version to a string of javascript.
update: { "$set" : {
"Data": "Here is new data!",
"Version" : { "$code" : "db.eval('getNextSequence(\"Version:CollectionName\")')" }
}
}
How can I get MongoDB C# client to serialize an Update document with my db.eval function call in it?
I have tried to add a new BsonValue type in my assembly which I would serialize down to db.eval(''); However there is a BsonType enum which I cannot modify, without making a mod to MongoDB which I would not like to do incase of any issues with the change, compatibility etc.
I have also tried simply creating the Update document myself as a BsonDocument, however FindAndModify will only accept an IMongoUpdate interface which a simply a marker that at present I find superfluous.
I have just tried to construct the command manually by creating a BsonDocument myself to set the Value: db.eval, however I get the following exception:
A String value cannot be written to the root level of a BSON document.
I see no other way now than drop down to the Mongo stream level to accomplish this.
So I gave up with trying to get Mongo C# Client to do what I needed and instead wrote the following MongoDB function to do this for me:
db.system.js.save(
{
_id : "optimisticFindAndModify" ,
value : function optimisticFindAndModify(collectionName, operationArgs) {
var collection = db.getCollection(collectionName);
var ret = collection.findAndModify(operationArgs);
return ret;
}
}
);
This will get the collection to operate over, and execute the passed operationArgs in a FindAndModify operation.
Because I could not get the shell to set a literal value (ie, not a "quoted string") on a javascript object, I had to to this in my C# code:
var counterName = "Version:" + CollectionName;
var sequenceJs = string.Format("getNextSequence(\"{0}\")", counterName);
var doc = entity.ToBsonDocument();
doc.Remove("_id");
doc.Remove(versionMap.ElementName);
doc.Add(versionMap.ElementName, "SEQUENCEJS");
var findAndModifyDocument = new BsonDocument
{
{"query", query.ToBsonDocument()},
{"update", doc},
{"new", true},
{"fields", Fields.Include(versionMap.ElementName).ToBsonDocument() }
};
// We have to strip the quotes from getNextSequence.
var findAndModifyArgs = findAndModifyDocument.ToString();
findAndModifyArgs = findAndModifyArgs.Replace("\"SEQUENCEJS\"", sequenceJs);
var evalCommand = string.Format("db.eval('optimisticFindAndModify(\"{0}\", {1})');", CollectionName, findAndModifyArgs);
var modifiedDocument = Database.Eval(new EvalArgs
{
Code = new BsonJavaScript(evalCommand)
});
The result of this is that I can now call my Sequence Javascript, the getNextSequence function, inside the optimisticFindAndModify function.
Unforunately I had to use a string replace in C# as again there is no way of setting a BsonDocument to use the literal type db.eval necessary, although Mongo Shell likes it just fine.
All is now working.
EDIT:
Although, if you really want to push boundaries, and are actually awake, you will realize this same action can be accomplished by performing an $inc on the Version field.... and none of this is necessary....
However: If you want to follow along to the MongoDB tutorial on how they to say to implement concurrency, or you just want to use a function in a FindAndModify, this will help you. I know I'll probably refer back to it a few times in this project!
I'm having a lot of trouble getting query results for certain collections in Meteor.
I have set
idGeneration : 'MONGO'
in the collection definitions, and in the mongo shell these collections look like this :
the document i want, call it documentW (from CollectionA) = {
"_id" : ObjectId("7032d38d35306f4472844be1"),
"product_id" : ObjectId("4660a328bd55247e395edd23"),
"producer_id" : ObjectId("a5ad120fa9e5ce31926112a7") }
documentX (from collection "Products") = {
_id : ObjectId("4660a328bd55247e395edd23")
}
documentY (from collection "Producers") = {
_id : ObjectId("a5ad120fa9e5ce31926112a7")
}
If i run a query like this in Meteor
CollectionA.findOne({ product_id : documentX._id, producer_id : documentY._id})
I'm expecting to get my documentW back... but I get nothing.
When I run this query in the mongo shell
db.collectiona.find({ product_id : ObjectId("4660a328bd55247e395edd23"), producer_id :
ObjectId("a5ad120fa9e5ce31926112a7") })
I get my documentW back no problem.
Of course in Meteor if I call
console.log(documentX._id)
I get this
{ _str : "4660a328bd55247e395edd23" }
Anyone have any ideas what is going on here ? I have tried all kinds of things like
Meteor.Collection.ObjectID(documentX._id._str)
but the search still returns empty...
Running the latest 0.7.0.1 version of Meteor...
I don't know if this answers your question, but I can't put this code in a comment. This code is working for me, trying to follow what I believe you are trying to do:
Products = new Meteor.Collection("products", {
idGeneration: "MONGO"
});
Producers = new Meteor.Collection("producers", {
idGeneration: "MONGO"
});
CollectionA = new Meteor.Collection("a", {
idGeneration: "MONGO"
});
Products.insert({
foo: "bar"
});
Producers.insert({
fizz: "buzz"
});
var documentX = Products.findOne();
var documentY = Producers.findOne();
CollectionA.insert({
product_id: documentX._id,
producer_id: documentY._id
});
var documentW = CollectionA.findOne({
product_id: documentX._id,
producer_id: documentY._id
});
console.log(documentW); // This properly logs the newly created document
This is on 0.7.0.1. Do you see anything in your code that diverges from this?
I have an aggregation query on a students collection that is returning two sets of results
for each student like this
{ _id: 1543,
name: 'Bill Jackson',
scores: { type: 'homework', score: 38.86823689842918 } }
{ _id: 1543,
name: 'Bill Jackson',
scores: { type: 'homework', score: 15.861613903793295 } }
That's working fine. Now in the callback I want to remove one of the scores for each student. I use ugly nested conditionals below to isolate which of the two records I want to remove, and, once that's achieved I create a find and Modify query to remove the doc but there's no evidence of it getting run. Neither the error or success callback to the findAndModify are getting run, however I am able to log that I'm inside the area where the findAndModify is getting called.
Is it possible to query the db in the callback to an aggregation? If not, how should I perform an operation that persists in the db?
//aggregation query ommitted
, function(err, result) { //callbackstarts here with result of aggregation query that returns two records for each student
for (var i=0; i<result.length; i++) {
var id = result[i]['_id'];
if (id === result[i]['_id']){
if (foo && foo === result[i]['_id']){
//if we're in here, we know we need to remove score associated with this result[i]['_id']
//create findAndModify to remove the record
var query = { '_id' : result[i]['_id']}
var sort = []
var operation = { '$pull' : { 'scores.score' : result[i]['scores']['score'] } };
var options = []
console.log('this code is getting called but findAndModify not')
db.collection('students').findAndModify(query, sort, operation, options,function(err, doc) {
if(err) throw err;
if (!doc) {
console.log("record not found");
}
else {
console.log("changed doc" + doc);
}
});
}else {
var foo = result[i]['_id'] //part of logic to isolate which of two records to remove
}
Running into problems getting any data out of mongo using mongoose. The connection seems fine as i've got debugging statements that are being printed out. I've searched high and low for what could be causing this but afaik I'm setting up the schema and collections fine.
here's what i have in a file called posts.js:
var mongoose = require('mongoose');
var db = mongoose.connect('mongodb://localhost:27017/sister', function(err) {
if (err) throw err;} //this does not get printed
);
mongoose.connection.on("open", function(){
console.log("mongodb is connected")} //this gets printed
);
var Schema = mongoose.Schema;
var thePost = new Schema({
name : String
});
mongoose.model('post', thePost);
var posts = db.model('post');
posts.find({}, [], function(err, calls) {
console.log(err, calls, calls.length); //prints out: null [] 0
});
To seed the data, I've done this in my mongo shell, which inserts a document and then shows that find all can find it:
> randumb = { name : 'emile' };
{ "name" : "emile" }
> db.post.insert(randumb);
> db.post.find({});
{ "_id" : ObjectId("4e775e8cc24f31883fdafbab"), "name" : "emile" }
try changing
var posts = db.model('post');
to
var posts = mongoose.model('post');
To keep it even shorter, try and change:
mongoose.model('post', thePost);
var posts = db.model('post');
to:
var posts = mongoose.model('post', thePost);