I am trying to update all documents in my collection which have fields containing any one of the values in my javascript array. I keep getting a '$in needs an array' error. I do not understand how to convert the javascript object into an array that mongo will accept.
Here is my code for the node backend:
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("test");
var myquery = { transferID: {$in: {idStore}}};
var newvalues = {$set: {redAlert: "1"} };
dbo.collection("myCollection").updateMany(myquery, newvalues, function(err, res) {
if (err) throw err;
console.log(res.result.nModified + " document(s) updated");
db.close();
});
});
Here is my array:
var idStore = [123, 456, 789]
There is no problem with your array, but the problem is with your query, you are passing idStore with curly braces({}), which makes it an object, thats why it sis throwing that error.
change your query to this and try :
var myquery = { transferID: {$in: idStore}};//without {}
Related
How do we query in mongo where in the results would not have duplicates , I have tried using distinc but it does not seem to work.
Query
keystone.list('Customer').model.find().sort('name').where('vin').in([vin]).exec(
function (err, results) {
if (err || !results.length) {
return next(err);
}
.....
keystone.list('Customer').model.find().distinct('customer_id')
.where('fieldName', 'fieldValue')
.exec(function(err, result) {
//array of _ids
});
Then pass all the ids in a $in query to get all the records.
I have some code that pulls all documents from a collection and puts it onto a webpage. a simplified version looks like this:
var mongodb = require("mongodb"),
express = require("express"),
mongoServer = new mongodb.Server('localhost', 27017),
dbConnector = new mongodb.Db('systemMonitor', mongoServer),
db;
var app = new express();
app.get('/drives', function(req, res) {
db.collection('driveInfo', function(err, collection) {
if (err) throw err;
collection.find({}, function(err, documents) {
res.send(documents);
});
});
});
dbConnector.open(function(err, opendb) {
if (err) throw err;
db = opendb;
app.listen(80);
});
I have a driveInfo collection which contains a long list of documents. Each document contains nested objects. What I would like to do, is whenever someone visits /drives in their browser, to print the entire collection as a json object so that I can grab everything with jquery later (beginnings of an api)
However, I get an error saying "TypeError: Converting circular structure to JSON". The error on the page points to this line of code:
collection.find({}, function(err, documents) {
res.send(documents);
});
I'm unsure what the problem is, or where the self-reference is. Am I not querying the collection properly?
Not sure what version of the API you are using, but i think that your syntax might be wrong looking at the API spec:
http://docs.mongodb.org/manual/reference/method/db.collection.find/
This is the declaration:
db.collection.find(<criteria>, <projection>)
And you are definitely misusing the projection parameter. Passing a callback like you are doing seems to return the db object in the result, which is causing the circular error during JSON serialization in express.
The correct code for the find all operation should be something like:
collection.find({}).toArray(function(error, documents) {
if (err) throw error;
res.send(documents);
});
In my case I was getting the error because I was querying(using mongoose find method) without doing an await. Please see below
Query that gave the error (as I haven't executed this query using await) :
const tours = Tour.find({
startLocation: {
$geoWithin: { $centerSphere: [[longitude, latitude], radius] }
}
});
Error that I got on postman due to this :
"message": "Converting circular structure to JSON\n --> starting at object with constructor 'NativeTopology'\n | property 's' -> object with constructor 'Object'\n | property 'sessionPool' -> object with constructor 'ServerSessionPool'\n --- property 'topology' closes the circle"
How I got rid of the above error (added await) :
const tours = await Tour.find({
startLocation: {
$geoWithin: { $centerSphere: [[longitude, latitude], radius] }
}
});
callback option is from Mongoose not from MongoDB see docs.
// Mongoose Docs : callback option
MyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {});
// Example
app.get( '/api/users' , (req,res,done)=>{
let getUsers = NewUser.find({},(err,data)=>{
if(err) return done(err);
res.json(data)
});
});
Look that the response is into callback that in your case it would be
YourModel.find({}, function(err, documents) {
if(err) return done(err);
res.send(documents); // <-- here
});
// <-- not here
In Mongo there is a cursor method to access the documents next() see docs :
var myCursor = db.bios.find( );
var myDocument = myCursor.hasNext() ? myCursor.next() : null;
if (myDocument) {
var myName = myDocument.name;
print (tojson(myName));
}
You can find CRUD operations in mongo docs at manual/crud. In Query Documents you will see db.inventory.find( {} ) : To select all documents in the collection, pass an empty document as the query filter parameter to the find method.
Async/Await function solution : Mongo Docs
app.get( '/api/users' , async (req,res)=>{
const getUsers = await NewUser.find({});
res.json( getUsers );
})
< callback > solution : Mongoose Docs.
app.get( '/api/users' , (req,res,done)=>{
let getUsers = NewUser.find({},(err,data)=>{
if(err) return done(err);
res.json(data)
});
});
const res1 = await db.collection("some-db").find()
Here, res1 will contain a "cursor" which has a circular structure, hence the given error is thrown.
Try adding const res2 = await res1.toArray() to the code.
Here, res2 will now contain an array of documents, pointed by cursor res1, which is the documents you were querying for.
I want to query a collection and update each document using some value that i will get from another query which is gonna be built with some info from the returned document.
const mongoose = require('mongoose');
const userModel = {
country: { type: String }
newField: { type: String }
};
const myUsersModel = mongoose.model('user',userModel);
myUsersModel.find({country:"USA"}).forEach(function (doc) {
// another query here into a relation Database:
let anotherQuery = 'SELECT * FROM myTable WHERE name=' + doc.name;
mySQLConnection.query(
anotherQuery,
function selectCb(err, results, fields) {
if (err) {
console.log("ERROR: " + err.message);
throw err;
}
console.log("Got "+results.length+" Rows:");
let updatedInfo = results.SomeField;
// update the mongoose doc:
doc.newField = updatedInfo;
myUsersModel.save(doc);
});
mySQLConnection.end(function(err) {
console.log("connection ended.");
});
mongoose.connection.close();
});
I am getting the following error:
TypeError: myUsersModel.find(...).forEach is not a function
myUsersModel.find({country:"USA"})
.then(users=>users.forEach //users might be null here btw
Or if you want to keep your callback style
myUsersModel.find({country:"USA"}, function(err, users) {
if (err) throw err;
users.forEach
If a callback is not provided, Model.find returns an instance of Query and not an instance of Array.
Hence, you can not use forEach as Query is not an Array.
I have a JSON object like this
{ "messages":["{date: 2017-8-23 12:50:05, name: aaa, msg: zzz}"]}
I want to push more objects to messages array after every message from user in Node.js but I only clone JSON object. How to fix this?
This is my code:
const JSONTemplate = (filePath, date, name, msg) => {
let obj = {
messages: [],
};
obj.messages.push(`{date: ${date}, name: ${name}, msg: ${msg}}`); //add some data
json = JSON.stringify(obj);
fs.appendFile(filePath, json, (err) => {
if (err) throw err;
}); }
You can try to put real object instead of string representation
obj.messages.push({date, name, msg});
But your question is still unclear for me. There is a mistake in string representation. You can not parse back your serialized object, because you miss apostrophe in your string.
And maybe you cannot get array of multiple values, because your rewrite your array by every function call.
const JSONTemplate = (filePath, date, name, msg, array = []) => {
let obj = {
messages: array,
};
obj.messages.push({date, name, msg}); //add some data
json = JSON.stringify(obj);
fs.appendFile(filePath, json, (err) => {
if (err) throw err;
}); }
if you want to append JSON data first you read the file and after that you could overwrite that.
const JSONTemplate = (filePath, date, name, msg) => {
fs.readFile(filePath, function (err, data) {
var json = JSON.parse(data);
//add some data
json.messages.push(JSON.stringify({date: ${date}, name: ${name}, msg: ${msg}}));
fs.writeFile(filePath, json, (err) => {
if (err) throw err;
});
});
}
also it's good practices to use try..catch to error handling when dealing with sync function like JSON.parse(), fs.readFileSync etc.
try{
var json = JSON.parse(data);
}catch(e){
throw e
}
Happy coding
I'm developing a express.js application, without mongoose.
What I'm trying to do is, to encapsulate calls to mongodb inside a function, pass the function some parameter and get the data back from mongodb.
The problem I'm running into is explained by the code below
function get_data()
{
var mongo = require('mongodb'),Server = mongo.Server,Db = mongo.Db;
var server = new Server('localhost', 27017, {auto_reconnect: true});
var db = new Db('test', server);
db.collection('test_collection', function(err, collection) {
collection.find().toArray(function(err, items) {
var data = items;
});
});
console.log(data);
console.log("in get");
return data;
}
How do I return the items Array I pulled from mongo db from this function.
I want to know how scoping works in javascript and how do I put the items in a variable and return them from the get_data function.
After the answer
I fixed the code. It now works and looks like this.
function get_data(callback) {
var mongo = require('mongodb'),Server = mongo.Server,Db = mongo.Db;
var server = new Server('localhost', 27017, {auto_reconnect: true});
var db = new Db('test', server);
db.open(function(err, db) {
if (err) return callback(err);
db.collection('test_collection', function(err, collection) {
if (err) return callback(err);
collection.find().toArray(callback);
});
});
}
get_data(function(err, items) {
// handle error
console.log(items);
});
Since the items are retrieved from MongoDB asynchronously, the function get_data needs to accept a callback that will be used to return the results. I believe you'll also need to explicitly open the database connection.
function get_data(callback) {
...
db.open(function(err, db) {
if (err) return callback(err);
db.collection('test_collection', function(err, collection) {
if (err) return callback(err);
collection.find().toArray(callback);
});
});
}
get_data(function(err, items) {
// handle error
console.log(items);
});