loading and running an aggregation in mongo shell - mongodb

I've coded an aggregation I want to run on a collection in the mongo shell. If I paste it directly into the shell, I have to do it line by line which is tedious and slow, especially when it doesn't work and I have to do it over. Therefore, I put it in a .js document and loaded it like this load("myaggregation.js") but that only returns true if the code is valid. How do I run the aggregation after loading it? I can't find any documentation about this. Do I have to use the nodejs driver?

Put your aggregation code in a function:
function my_aggregate() {
return db.foo.aggregate( [ ... ] );
}
and store that in your .js file.
Then run load to load it. You can also pass the filename on the commandline using the --shell commandline flag which will start the interactive shell after running any specified .js files.
Once the file is run your new function will be available to execute. Simply type
my_aggregate()
Update You do have to use an explicit return which I failed to mention. So in your case you would want something like:
function my_aggregate() {
return db.zips.aggregate([{ $match: { state: { $in: [ "CA", "NY" ] } }},{ $group:{ _id : { "state" : "$state","city" : "$city" }, pop : { $sum: "$pop"}}},{ $match: { pop: { $gt: 25000 } }},{$group:{ _id : { "city" : "$city"}, pop : { $avg: "$pop"}}}]);
}

Have you seen http://docs.mongodb.org/manual/tutorial/write-scripts-for-the-mongo-shell/?
Something like: mongo localhost:27017/test myjsfile.js
It also says that "You can execute a .js file from within the mongo shell, using the load() function".

I know this is a late answer but I found a nice way to handle this:
Create a js file containing your aggregate query:
use blog;
db.posts.aggregate([
... my query ...
]);
then you can simply cat and pipe the file to mongo client:
cat myfile.js | mongo

script.js file content:
aggrQuery = db.foo.aggregate([
{$group: {_id: '$bar', pop: {$max: '$buz'}}}
])
in the mongo shell:
> load('/file/location/script.js');
true
>aggrQuery
here will be output

Related

mongodb, how to use $not filter in query

I have what should be a fairly simple query I'm trying to run in mongodb compass:
{ $and: [ { Source: "hostname" }, { Message: { $not: /.*unexpected data.*1234.*/ } } ] }
Basically, my document model contains a Source field and a Message field.
I need to query for all documents where the Source equals a given "hostname" and the Message does not contain "unexpected data...1234"
Everything works fine when I DO NOT include the $not filter on the regular expression... so I get all the documents where this message is contained... but now I need all the other messages where this is NOT contained... and I can't figure out how to use $not properly.
The example given in the MongoDb manual only shows using $not with one statement... but even this doesn't work for me for some reason...
{ Message: { $not: /.*unexpected data.*1234.*/ } }
Again, it works fine without the $not... what am I missing?
Edit:
Here is an image of what I'm talking about, placing this filter in MongoDb Compass, it indicates that the filter is incorrect... Is MongoDb Compass for some reason incapable of running complex filters?
Please try with $regex which should work:
find( { $and: [ { Source: "hostname" }, { Message: { $not: { $regex: /.*unexpected data.*1234.*/ } } } ] })
MongoDB Compass only supports regex surrounded by single quotes, not forward slashes. So $regex: /.*unexpected data.*1234.*/ should be $regex: '.*unexpected data.*1234.*'.
https://jira.mongodb.org/browse/COMPASS-2993

How to subtract two dates in Mongo

Consider this code. I have this query in a 3T Studio aggregate query.
{
"book.newpublisheddate": {$subtract : [ {$date: "book.published"}, {$date: "1970-01-01T00:00:00.000+0000"}] }
}
I cannot use code like {$subtract : [ "book.published", new Date()] } because it says it is not valid json. I am using mongo 3.6.13.
Using this collection:
> db.test.find()
{
"_id": 0,
"book": {
"published": ISODate("2019-08-04T22:49:14.416Z")
}
}
This aggregation works:
> db.test.aggregate([
{$project:
{dateDiff: {$subtract: ['$book.published', ISODate('1970-01-01')] }}}
])
{ "_id": 0, "dateDiff": NumberLong("1564958954416") }
Note that you don't need to surround book.published inside a $date, rather just use $book.published. You also need ISODate('1970-01-01').
This works inside Studio3T "shell mode" and inside the mongo shell.
No idea where do you want to use {$subtract : [ "book.published", new Date()] }. Assuming it is mongo shell - most likely you are missing a dollar sign before "book.published". Try "$book.published" - use $ to reference fields.

Mongo shell aggregation query issue

I am fairly new to MongoDB and I am facing a strange issue.
I've been able to build an aggregation pipeline using a compass.
The query produces the expected result in the GUI but it returns nothing in mongo shell.
Here is the query :
db.searchQueryCollection.aggregate([{
$match: {
time_stamp: {
$gte: ISODate("2018-08-13 17:33:20.000"),
$lt: ISODate("2018-08-13 19:33:20.000")
}
}
}, {
$group: {
_id: "$purpose",
groupedPurpose: {$push: "$purpose"}
}
}, {$project: {number_of_results: {$size: "$groupedPurpose"}}}])
Here is the output in compass :
Any idea on what's going wrong?
In mongo shell, you should use as below:
db.getCollection("YOUR_COLLECTION_NAME").aggregate([{
$match: {
time_stamp: {
$gte: ISODate("2018-08-13 17:33:20.000"),
$lt: ISODate("2018-08-13 19:33:20.000")
}
}
}, {
$group: {
_id: "$purpose",
groupedPurpose: {$push: "$purpose"}
}
}, {$project: {number_of_results: {$size: "$groupedPurpose"}}}])
If none of your aggregation queries return a result, you may be connected to the wrong database.
If you're connecting using a database driver, check your connection string. In the following example, the database name is at the end of the connection string.
MONGODB_URI=mongodb+srv://username:password#cluster0.abcdefg.mongodb.net/databasename
If you're connecting using MongoDB shell, run the following two commands:
show dbs;
admin 288.00 KiB
config 328.00 KiB
local 62.66 MiB
mydatabase 1.24 MiB
use mydatabase;

How to update a field value globally in mongodb

Is there a easier way to update field text in mongodb globally?
I don't have a mongodb knowledge but some thing like this,
Update "all collections that has field1" set field1=some where field1=1234
Please take a look at mysql solution using db dumps:
Similar to Find and replace in entire mysql database
If the above is not possible what is the best way to go about writing a one time script to migrate data in mongodb? This is in linux environment.
To update multiple documents in the same collection, use the multi:true option when you do an update:
db.collection.update(
{ "field1": 1234 },
{ "$set": { "field1" : somevalue } },
{ multi: true }
);
MongoDB has no commands which affect more than one collection at a time, so you will have to execute this for every collection separately. When you want to do this in the shell, you can perform the command on every collection separately with a script like this:
db.getCollectionNames().forEach( function(name) {
db[name].update(
{ "field1": 1234 },
{ "$set": { "field1" : somevalue } },
{ multi: true }
);
});

how to run aggregate query in mongodb client on RockMongo or mViewer

I've just started using mongo db, I'm using rockmongo client and my ubuntu terminal as another client. I' ve realized the query using group aggregation like this:
db.archiveImpl.group(
{
key: {accountID: true, phone: true },
cond: {'userId': "oiuoifas2309u"},
reduce: function(object, prev){ },
initial:{}
}
)
And the above query is not getting run in the rockmongo , I initially thought that the query was wrong. and I ran in on the terminal which pulls me the data. So I downloaded and installed mViewer and it didn't work either so I believe there is a way to run these kind of queries in mongo web clients
thanks for reading this .
You can run aggregate query in "tools->command" panel in your homepage of rockmongo.
You may enter query in the input panel like this:
{
aggregate : "ns",
pipeline : [
...
]
}
That will be ok! I have tried, and it works!
Full Example:
{ aggregate : "COLLECTION_NAME",
pipeline : [
{ $unwind : "$SUB_ARRAY" },
{ $match: {"SUB_ARRAY.field": "value"}},
]
}