Mongodb find array of ids - mongodb

I have one array which has document ids.:
var ids = [ '5b3c7db4c079dc17dc75fc26', '5b3c7db4c079dc17dc75fc28' ]
I have one collection called Machines with documents inside.
I am trying to get documents from Machines collection using ids which are in my array.
Machines.find({ _id : { $in : ids } }).fetch();
this returns []

Try this:
var ids = [ ObjectId("5b3c7db4c079dc17dc75fc26"), ObjectId("5b3c7db4c079dc17dc75fc28") ]
Because Mongodb stores id as ObjectId("Actual Id")

Your
var ids = [ '5b3c7db4c079dc17dc75fc26', '5b3c7db4c079dc17dc75fc28' ]
looks like they're either hex string or native MongoDB BSON type ObjectID.
Try this for Meteor's Mongo:
import { Mongo } from 'meteor/mongo';
const ids = [
new Mongo.ObjectID('5b3c7db4c079dc17dc75fc26'),
new Mongo.ObjectID('5b3c7db4c079dc17dc75fc28'),
]
Machines.find({ _id : { $in : ids } }).fetch();
For better syntax, use .map() to get a new array of Mongo.ObjectID type IDs.
import { Mongo } from 'meteor/mongo';
const ids = ['5b3c7db4c079dc17dc75fc26', '5b3c7db4c079dc17dc75fc28', ...];
const mongoIds = ids.map(id => new Mongo.ObjectID(id));
Machines.find({ _id : { $in : mongoIds } }).fetch();
// if ids were ObjectIDs instead of literal strings
const objectIdToMongoIds = ids.map(id => new Mongo.ObjectID(id.toString()));
Machines.find({ _id: { $in: objectIdToMongoIds } });
meteor mongo es6 functional-programming

You can also try Machine.findById(req.params.id, () => {}

Related

Aggregate and update with mongoose

I want to use the aggregate method to make my querys and modify my database by a value, I tried with $set but my database is not modified.
Here is how I do my query:
var filter = req.body.filter
var search = [ { $match: filter }, { $set: {item: "2"} }, { $sample: { size: 1 } }]
const result = await dataModel.aggregate(search)
I know there is also findOneAndUpdate but I would like to keep aggregate because I also want to use $project in my pipelines
thanks in advance !
You can use FindOneAndUpdate for change your db

Mongoose query an array contain one of value in another array

How do I check if an element of an array belongs to another array in Mongoose? For example, I have a document:
const userSchema = new mongoose.Schema({
name: String,
favor:Array
})
user1 = {
name:'John',
favor : ['banana', 'apple', 'eggs'].
}
user 2= {
name:'Ethan',
favor : ['apple', 'eggs'].
}
and I have an Array
const array = ['eggs', 'banana']
I want to get user1. How can I do with mongoose?
You should use $all operator for this scenario
db.collection.find({
favor: {
$all: [
"eggs",
"banana"
]
}
})
https://docs.mongodb.com/manual/reference/operator/query/all/

MongoDB - Is it possible to compare documents through the _id field?

As the title clearly describes, I need to make comparison between documents through the auto-generated _id field. For example, is it possible to make a query such as "newer/older records than the id 5e120e38c149d02d27ea750c" something like greater-than/less-than operations?
Something like the below one didn't do what it was expected:
num_apps = db.app.count_documents({"_id": {"$lt": "5e120e38c149d02d27ea750c"}})
p.s. Using the PyMongo module.
You can do that, but the problem with your query is you're passing a string as input but the type of _id in DB is ObjectId(), So input should match with it. So convert it before querying DB.
If using native mongodb driver :
const ObjectId = require('mongodb').ObjectID;
num_apps = db.app.count_documents({ "_id": { "$lt": ObjectId("5e120e38c149d02d27ea750c") } })
If using mongoose :
const mongoose = require('mongoose');
let id = mongoose.Types.ObjectId('5e120e38c149d02d27ea750c');
num_apps = db.app.count_documents({ "_id": { "$lt": id } })
If using pymongo :
from pymongo import MongoClient
from bson.objectid import ObjectId
num_apps = db.app.count_documents({ "_id": { "$lt": ObjectId("5e120e38c149d02d27ea750c") } })

Use of $sum inside set - Mongodb

I have the following problem.
I want to create inside my mongodb database a new field for each documentation. This field should consist as a value the sum of two other fields of the documentation.
I tried this:
db.collection('restaurants').updateMany(
{}, { $set:
{ allScores: {$sum: "$grades.score"} }
}
)
but it doesn't work. I get the following error:
The dollar ($) prefixed field '$sum' in 'allScores.$sum' is not valid for storage.
Why can't I use $sum inside of $set?
And what can I do instead?
The database I used can be found here: https://www.w3resource.com/mongodb-exercises/
Thanks!
Julia
const MongoClient = require('mongodb').MongoClient;
ObjectID = require('mongodb').ObjectID;
// Connection URL
const url = 'mongodb://localhost:27017';
// Database Name
const dbName = 'myproject';
// Use connect method to connect to the server
MongoClient.connect(url, { useNewUrlParser: true }, function(error, client) {
if(error) {
return console.log('An error occured!')
}
console.log("Connected successfully to server");
const db = client.db(dbName);
var objectId = new ObjectID();
db.collection('restaurants').updateMany(
{}, { $set:
{ allScores: {$sum: "$grades.score"} }
}
)
You can use aggregate() with $out to do that:
db.collection('restaurants').aggregate([
{$addFields : {allScores : {$sum : "$grades.score"}}},
{$out : "restaurants"}
])
What this code does:
1- Find all documents inside restaurants;
2- Add the field allScores to each document;
3- Save all documents back to the collection restaurants;

Complex mongodb document search

I'm attempting to write a find query where one of the keys is unknown at the time the query is run, for example on the following document I'm interested in returning the document if "setup" is true:
{
"a": {
"randomstringhere": {
"setup": true
}
}
}
However I can't work how to wildcard the "randomstringhere" field as it changes for each document in the collection.
Can somebody help?
There is not much you can do with that. But you can modify your collection schema like
{
"a": [
{
"keyName": "randomstringhere",
"setup": true
},
//...
]
}
you can than write query to look
{
'a' : { $elemMatch: { setup: true } ,
}
You can't do this with a single query, as with the current design you would need a mechanism to get all the random keys that you need and then assemble the query document that uses the $or operator in the event that you get a list of variable key name.
The first part of your operation is possible using Map-Reduce. The following mapreduce operation will populate a separate collection called collectionKeys with all the random keys as the _id values:
mr = db.runCommand({
"mapreduce": "collection",
"map" : function() {
for (var key in this.a) { emit(key, null); }
},
"reduce" : function() { },
"out": "collectionKeys"
})
To get a list of all the random keys, run distinct on the resulting collection:
db[mr.result].distinct("_id")
Example Ouput
["randomstring_1", "randomstring_2", "randomstring_3", "randomstring_4", ...]
Now given the list above, you can assemble your query by creating an object that will have its properties set within a loop. Normally your query document will have this structure:
var query = {
"$or": [
{ "a.randomstring_1.setup": true },
{ "a.randomstring_2.setup": true },
{ "a.randomstring_3.setup": true }
]
};
which you can then use in your query:
db.collection.find(query)
So using the above list of subdocument keys, you can dynamically construct the above using JavaScript's map() method:
mr = db.runCommand({
"mapreduce": "collection", // your collection name
"map" : function() { // map function
for (var key in this.a) { emit(key, null); }
},
"reduce" : function() { }, // empty reducer that doesn't do anything
"out": "collectionKeys" // output collection with results
})
var randomstringKeysList = db[mr.result].distinct("_id"),
orOperator = randomstringKeysList.map(function (key){
var o = {};
o["a."+ key +".setup"] = true;
return o;
}),
query = { "$or": orOperator };
db.collection.find(query);