Scheduled backup MongoDB database using mongodump and cron

mkdir backup
touch monitoring.sh
#!/bin/bash
 
currentDate=`date +"%Y%m%d%H%M"`
dirName="monitoring_$currentDate"
filePath=/home/mahmood/backup/$dirName
mkdir $filePath
mongodump --db monitoring --out $filePath
sudo chmod +x monitoring.sh
sudo crontab -e
30 4 * * * /home/mahmood/backup/monitoring.sh

References
https://stackoverflow.com/questions/35574603/run-cron-job-everyday-at-specific-time
https://tecadmin.net/get-current-date-and-time-in-bash/
https://askubuntu.com/questions/350861/how-to-set-a-cron-job-to-run-a-shell-script
https://coderwall.com/p/hdmmnq/easy-automatic-nightly-backups-for-mongodb

Backup MongoDB using mongodump

Backup a Whole Database

mongodump --db mydb
sudo mongodump --db mydb --out /var/backups/mongo

Backup a Single Collection

mongodump -d mydb -o /var/backups/mongo --collection users

Restore a Whole Database

sudo mongorestore --db mydb /var/backups/mongo/mydb

Restore a whole collection

mongorestore -d mydb -c users mydb/users.bson

Taking Regular Backups Using Mongodump/Mongorestore

sudo crontab -e

backup every day at 4:30 AM

30 4 * * * mongodump --db mydb

Archive output

mongodump --db monitoring --archive=monitoring_20190604.archive

Gzip output

mongodump --db monitoring --archive=monitoring_20190604.archive.gz --gzip

References
https://severalnines.com/blog/review-mongodb-backup-options
https://docs.mongodb.com/manual/reference/program/mongodump/

Query for Sub Document field in Spring Data Mongodb

To resolve this ambiguity you can use _ inside your method name to manually define traversal points. So our method name would end up like so:

List<Person> findByAddress_ZipCode(ZipCode zipCode);

References
http://docs.spring.io/spring-data/data-mongo/docs/current/reference/html/#repositories.query-methods.query-property-expressions
https://stackoverflow.com/questions/26887505/spring-data-mongodb-query-for-subdocument-field

Spring Data MongoDB – Indexes, Annotations and Converters

Indexed
This annotation marks the field as indexed in MongoDB

@QueryEntity
@Document
public class User {
    @Indexed
    private String name;
     
    ... 
}

Compound Indexes
MongoDB supports compound indexes, where a single index structure holds references to multiple fields.

@QueryEntity
@Document
@CompoundIndexes({
    @CompoundIndex(name = "email_age", def = "{'email.id' : 1, 'age': 1}")
})
public class User {
    //
}

Transient
As you would expect, this simple annotation excludes the field from being persisted in the database.

public class User {
     
    @Transient
    private Integer yearOfBirth;
    // standard getter and setter
 
}

Field
@Field indicates the key to be used for the field in the JSON document

@Field("email")
private EmailAddress emailAddress;

References
http://www.baeldung.com/spring-data-mongodb-index-annotations-converter

Spring Data MongoDB : Query document

Test Data

> db.users.find()
{ "_id" : ObjectId("id"), "ic" : "1001", "name" : "ant", "age" : 10 }
{ "_id" : ObjectId("id"), "ic" : "1002", "name" : "bird", "age" : 20 }
{ "_id" : ObjectId("id"), "ic" : "1003", "name" : "cat", "age" : 30 }
{ "_id" : ObjectId("id"), "ic" : "1004", "name" : "dog", "age" : 40 }
{ "_id" : ObjectId("id"), "ic" : "1005", "name" : "elephant", "age" : 50 }
{ "_id" : ObjectId("id"), "ic" : "1006", "name" : "frog", "age" : 60 }

BasicQuery example

BasicQuery query1 = new BasicQuery("{ age : { $lt : 40 }, name : 'cat' }");
User userTest1 = mongoOperation.findOne(query1, User.class);

System.out.println("query1 - " + query1.toString());
System.out.println("userTest1 - " + userTest1);

findOne example

Query query2 = new Query();
query2.addCriteria(Criteria.where("name").is("dog").and("age").is(40));

User userTest2 = mongoOperation.findOne(query2, User.class);
System.out.println("query2 - " + query2.toString());
System.out.println("userTest2 - " + userTest2);

find and $inc example

List<Integer> listOfAge = new ArrayList<Integer>();
listOfAge.add(10);
listOfAge.add(30);
listOfAge.add(40);

Query query3 = new Query();
query3.addCriteria(Criteria.where("age").in(listOfAge));

List<User> userTest3 = mongoOperation.find(query3, User.class);
System.out.println("query3 - " + query3.toString());

for (User user : userTest3) {
	System.out.println("userTest3 - " + user);
}

find and $gt, $lt, $and example

Query query4 = new Query();
query4.addCriteria(Criteria.where("age").lt(40).and("age").gt(10));

List<User> userTest4 = mongoOperation.find(query4, User.class);
System.out.println("query4 - " + query4.toString());

for (User user : userTest4) {
	System.out.println("userTest4 - " + user);
}

You can’t use Criteria.and() to add multiple criteria into the same field, to fix it, use Criteria.andOperator(), see updated example :

Query query4 = new Query();
query4.addCriteria(
	Criteria.where("age").exists(true)
	.andOperator(
		Criteria.where("age").gt(10),
                Criteria.where("age").lt(40)
	)
);

List<User> userTest4 = mongoOperation.find(query4, User.class);
System.out.println("query4 - " + query4.toString());

for (User user : userTest4) {
	System.out.println("userTest4 - " + user);
}

find and sorting example

Query query5 = new Query();
query5.addCriteria(Criteria.where("age").gte(30));
query5.with(new Sort(Sort.Direction.DESC, "age"));

List<User> userTest5 = mongoOperation.find(query5, User.class);
System.out.println("query5 - " + query5.toString());

for (User user : userTest5) {
	System.out.println("userTest5 - " + user);
}

find and $regex example

Query query6 = new Query();
query6.addCriteria(Criteria.where("name").regex("D.*G", "i"));

List<User> userTest6 = mongoOperation.find(query6, User.class);
System.out.println("query6 - " + query6.toString());

for (User user : userTest6) {
	System.out.println("userTest6 - " + user);
}

Method 2 : Generated Query Methods

public interface UserRepository 
  extends MongoRepository<User, String>, QueryDslPredicateExecutor<User> {
    ...
}

References
https://www.mkyong.com/mongodb/spring-data-mongodb-query-document/
http://www.baeldung.com/queries-in-spring-data-mongodb

how to get the last N records in MongoDB

.sort()

db.foo.find().sort({x:1});

The 1 will sort ascending (oldest to newest) and -1 will sort descending (newest to oldest.)

If you use the auto created _id field it has a date embedded in it … so you can use that to order by …

db.foo.find().sort({_id:1});

That will return back all your documents sorted from oldest to newest.

Natural Order

You can also use a Natural Order mentioned above …

db.foo.find().sort({$natural:1});

Again, using 1 or -1 depending on the order you want.

Use .limit()

Lastly, it’s good practice to add a limit when doing this sort of wide open query so you could do either …

db.foo.find().sort({_id:1}).limit(50);

or

db.foo.find().sort({$natural:1}).limit(50);

References
http://stackoverflow.com/questions/4421207/mongodb-how-to-get-the-last-n-records

Install MongoDB on OpenSuse

after install run

sudo nano /etc/mongodb.conf
disable security
# Security settings.
#security:
#  authorization: enabled

the restart service and run with config

mongod --config /etc/mongodb.conf

other commands

db.createUser(
  {
    user: "admin",
    pwd: "admin",
    roles: [ { role: "root", db: "admin" } ]
  }
);
db.createUser(
    {
      user: "mahmood",
      pwd: "12345",
      roles: ["readWrite"]
    }
);

References
https://docs.mongodb.com/v3.0/reference/configuration-options/
http://stackoverflow.com/questions/23943651/mongodb-admin-user-not-authorized
http://stackoverflow.com/questions/35881662/mongodb-error-not-authorized-to-execute-command
https://docs.mongodb.com/manual/tutorial/enable-authentication/
http://stackoverflow.com/questions/23003391/how-do-i-add-an-admin-user-to-mongo-in-2-6