Java Programming Questions | Java sample coding problems

This is a post dedicated to Java programming challenges that can be useful to refresh and validate your knowledge of Java.

Question 1

Write the output of the following code?

nt x = 1, y = 1, z = 0;
if (x == y | x < ++y) {
z = x + y;
} else {
z = 1;
}
System.out.println(z);

Question 2

Write the output of the following code?

nt x = 1, y = 1, z = 0;
if (x == y | x < ++y) {
z = x + y;
} else {
z = 1;
}
System.out.println(z);

Not Sure why the out of questions 1 and 2 are different read about Java short circuit and full evaluation.

Question 3

Write the output of the following code?

int period = 1, amt = 10;
float rate = 0.5f;
switch (period) {
case 4:
	amt += amt * rate;
case 3:
	amt += amt * rate;
case 2:
	amt += amt * rate;
case 1:
	amt += amt * rate;

	System.out.println("final amt : " + amt);
}

Also, try to run the above code after modifying case 4 as below

case 4:
    amt += amt * rate;
    break;

Question 4

Write the output of the following code?

public static void main(String... strings) {
	int localVal = 5;
	calculate(localVal);
	System.out.println(localVal);
}

public static void calculate(int calcVal) {
    calcVal = calcVal * 100;
}

Question 5

Write the output of the following code?

String str = ""; 
str  = 1 + 1 + "u";
System.out.println(str);
str  = "u" + 1 + 1;
System.out.println(str);
str  = "u" + (1 + 1);
System.out.println(str);

Happy Learning !!

Java Short-Circuit Evaluation | Java Operators

There are so many operators available in Java. Here we will discuss Java Short circuit operators and how they evaluate the given expression. As a Java developer, you must know these basics and how to use them effectively.

OperatorEvaluation
&& and ||Short-Circuit
& and |Full

Operator && and || are known as short-circuit operators and how they evaluate an expression is known as short circuit evaluation.

What exactly Short-circuit evaluation is?

The short circuit evaluation enables you to not evaluate the right-hand side AND or OR expression when the overall result of the expression can be predicted from the left-hand side value.

So for AND (&&), both parts must be true for the overall results to be true. For OR (||), one part must be true, either one of these. The other may be false, it doesn’t matter. The overall result will be true. And for exclusive OR (^), either part has to be true, and the other part has to be false for the overall result to become true.

Now, instead of the double ampersand (&&) and double vertical line (||), there are also single ampersand and single vertical line operators available, and they’re known as full evaluation versus the double ampersand and double vertical line, which are known as short circuit evaluation.

Refer to the below picture and see how the evaluation of these operators happens.

Java Short-Circuit Evaluation

Example

Now let’s understand this using the below code snippet.

 
int a = 3, b = 2;
boolean c = false;

c = (a > b && ++b == 3); 
System.out.println("value of c is "+c + " and b is "+b);

c = (a > b && ++b == 3);
System.out.println("value of c is "+c + " and b is "+b);

c = (a > b || ++b == 3); 
System.out.println("value of c is "+c + " and b is "+b);

c = (a < b || ++b == 3); 
System.out.println("value of c is "+c + " and b is "+b);

c = (a < b | ++b == 3); 
System.out.println("value of c is "+c + " and b is "+b);

c = (a > b & ++b == 3);
System.out.println("value of c is "+c + " and b is "+b);

c = (a < b ^ ++b == 3);
System.out.println("value of c is "+c + " and b is "+b);

c = (a > b ^ ++b == 3);
System.out.println("value of c is "+c + " and b is "+b);

//Output
value of c is true and b is 3
value of c is false and b is 3
value of c is false and b is 4
value of c is true and b is 4
value of c is true and b is 5
value of c is false and b is 6
value of c is true and b is 7
value of c is false and b is 8

Note: You don’t have to put round brackets around Booleans, but that may make your code a little bit more readable, just sort of from a visual point of view so the Boolean expression will stand out.

Output Explantion

Let’s understand the output of each line.

 c = (a > b && ++b == 3); 

For AND condition, both parts of the expression need to be true for the overall results to become true. So we have to evaluate both parts to tell that.

If you look at a Boolean expression, the double ampersand is AND, the first part evaluates to true and then ++b increment the b to 3 and it also evaluates to true. That’s why c is true and b is 3.

See the next line of code which is a copy of the first line but its output is different from the first line. In this case, the first condition evaluates to false as b is incremented to 3 in the first line. Hence the second part of the expression will not be evaluated.

 c = (a > b || ++b == 3);  

OR condition, here one part of the expression needs to be true for the overall results to become true. So we have to evaluate both parts to tell that.

If you look at a Boolean expression, the first part evaluates to false and then ++b increment the b to 4 and it also evaluates to false. That’s why c is false and b is 4.

The next line also used the OR operator but changed the first part of the condition to a < b.

 c = (a < b || ++b == 3);  

In this case the first part evaluates to true hence the second part of the expression is omitted from the evaluation. That’s why c is true and b is still 4.

The next line also used the OR operator but not the short circuit one. This time we used the full evaluation of OR (|) means a single vertical line. The difference in full evaluation is even if the first condition of the OR is true the second part will still be evaluated and it doesn’t impact the overall result of the expression.

 c = (a < b | ++b == 3);  

Hence, in the output of the above line value of c is true and b is incremented to 5.

The next line is having the full evaluation AND operator. These means don’t matter the first condition evaluates to true or false the second condition will be evaluated which is not the case when we use short circuit AND (&&) operator.

 c = (a > b & ++b == 3);  

In the above line the first condition is evaluated to false but still, the second condition is evaluated which is not the case when we use &&. Hence The value of c is false in the output of the above line but the b is still incremented to 6.

The next two lines of the code are using XOR (^) operator. This is also used for a full evaluation of both the expression. This will return true if one condition is true and another is false.

 c = (a < b ^ ++b == 3);  

Here the first condition is evaluated to true then it increments b to 7 and the second condition evaluates to false.

 c = (a > b ^ ++b == 3);  

The last line output value of c is false and b is 8. Here if you see the first condition is evaluated to false then it incremented b to 8 and that condition is false.

Conclusion

Here we discussed the &&, ||, &, | and ^ operators and how they evaluate a given condition. While using full evaluation the second part of the condition is evaluated doesn’t matter the first condition is evaluated to true or false.

Happy Learning !!

Read more

Refrence

How to use Java 8 Function and BiFunction Interface?

With all the other enhancements in Java 8 a new package java.util.function is also added to the Java library. In this post, we will discuss how to use the Function and BiFunction interface with examples. Both the interface are functional interface.

Function Interface Syntax

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

Salient Points of Function interface

  • It has been defined with the generic types T & R, where T is the type of the input and R is the output type.
  • Method apply() is the functional method (only abstract method in a functional interface). It takes an input t of type T and returns an output of type R.
  • It has two default method.
  • The first default method compose()  Returns a composed function that first applies the function to its input, and then applies this function to the result. If the evaluation of either function throws an exception, it is relayed to the caller of the composed function. In simple words, a composed function that first applies the before function and then applies its own function to the result of before.
  • The second default method is andThen() is inverse of the compose function. It is a composed function that first applies its own function to the input and then applies the after function to the result.
  • Function interface has one static method identity() which returns a function that always returns its input argument.

BiFunction Interface

@FunctionalInterface
public interface BiFunction<T, U, R> {
    R apply(T t, U u);

    default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t, U u) -> after.apply(apply(t, u));
    }
}

Salient Points of BiFunction interface

  • It has been defined with the generic types T, U & R, where T and U are the types of the first and second input and R is the output type.
  • Method apply() is the functional method that applies this function to the given input T and U and returns the output of Type R.
  • The default method andThen() is a composed function that first applies its own function to the input and then applies the after function to result.

Example

In this example, we will use a class Product to demonstrate the Function interface.

class Product{
	private int id;
	private String name;
	private String desc;
	
	public Product(int id, String name, String desc) {
		super();
		this.id = id;
		this.name = name;
		this.desc = desc;
	}

	@Override
	public String toString() {
		return "Product [id=" + id + ", name=" + name + ", desc=" + desc + "]";
	}

	public int getId() {
		return id;
	}

	public String getName() {
		return name;
	}

	public String getDesc() {
		return desc;
	}

	public void setName(String name) {
		this.name = name;
	}
	
} 

Function Interface apply method

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

public class FunctionDemo {
	static List<Product> products = new ArrayList<>();	
	
	static Function<Product, String> getProductNameFunction = Product::getName;
		
	public static void main(String[] args) {
		prepareData();
		List<String> productNames = new ArrayList<>(); 
		products.forEach(p ->{
			productNames.add(getProductNameFunction.apply(p));
		});
		System.out.println("productNames => "+productNames);		
	}

	static void prepareData() {
		for(int i =1 ; i<= 10; i++) {
			products.add(new Product(i, "product name "+i, "product desc "+i));
		}
	}
}

In the above code snippet, we have created a list of Products and a Function getProductNameFunction which will convert the list of Products into a list of String containing product names.

Function Interface compose method

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.function.Function;

public class FunctionDemo {
	static List<Product> products = new ArrayList<>();	
	
	static Function<Product, String> getProductNameFunction = Product::getName;
	
	static Function<Product, Product> composeBeforeFunction = (Product p)->{
		String name = p.getName().replace(" ", " "+new Random().nextInt());
		p.setName(name);
		return p;
	};
		
	public static void main(String[] args) {
		prepareData();
		
		List<String> productNames = new ArrayList<>(); 
		products.forEach(p ->{
			productNames.add(getProductNameFunction.compose(composeBeforeFunction).apply(p));
		});
		System.out.println("productNames => "+productNames);		
	}

	static void prepareData() {
		for(int i =1 ; i<= 10; i++) {
			products.add(new Product(i, "product "+i, "product desc "+i));
		}
	}
}

Here we have created a list of products and a new Function composeBeforeFunction and we also use getProductNameFunction from apply example. Here when we run this code snippet as per the description of compose() method composeBeforeFunction will apply and it will add a random string to the product name and then the getProductNameFunction will be applied which will return a list of the product name.

Function Interface andThen method

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

public class FunctionDemo {
	static List<Product> products = new ArrayList<>();	
	
	static Function<Product, String> getProductNameFunction = Product::getName;
	
	static Function<String, String> andThenFunction = (String s)-> s.substring(s.length()-1,s.length());
	
	public static void main(String[] args) {
		prepareData();
		
		List<String> productNames = new ArrayList<>(); 
		
		products.forEach(p ->
			productNames.add(getProductNameFunction.andThen(andThenFunction).apply(p))
		);
		
		System.out.println("productNames => "+productNames);		
	}

	static void prepareData() {
		for(int i =1 ; i<= 10; i++) {
			products.add(new Product(i, "product "+i, "product desc "+i));
		}
	}
}

In this example, we have created a list of products and a new Function andThenFunction also we have used getProductNameFunction from apply example. Here when we run this code snippet as per the description of andThen() method getProductNameFunction will apply first and then the andThenFunction will be applied which will return a list of String only having the last char of the product name.

Function Interface identity method

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class FunctionDemo {
	static List<Product> products = new ArrayList<>();	
	
	public static void main(String[] args) {
		prepareData();
		
		Map<Integer, Product> productmap = products.stream()
				.collect(Collectors.toMap(Product::getId, Function.identity()));
		
		System.out.println("productmap => "+productmap);		
	}

	static void prepareData() {
		for(int i =1 ; i<= 10; i++) {
			products.add(new Product(i, "product "+i, "product desc "+i));
		}
	}
}

In this example, we have converted the list of products into a Map of using the identity() method.

If we haven’t used the identity() method to create a Map we have to use the other way like below.

Map<Integer, Product> productmapWithForeach = new HashMap<>();
		
products.forEach(product -> productmapWithForeach.put(product.getId(),
 product));

BiFunction apply method

public class FunctionDemo {	
		
	public static void main(String[] args) {
				
		 BiFunction<Integer, Integer, Integer> addFunction = (t, u) -> t + u;
		 
		 int sum = addFunction.apply(10, 20);
	 
		 System.out.println("sum is => +sum");

		
	}
}

Conclusion

In this post, we have discussed Function and BiFunction Interface and how can we use these functions to write more concise and clean code.

Recommended Read

Java 8 Method Reference
Java 8 Stream API
Java 8 comparison using Lambda

Happy Learning !!

Understanding and preventing memory leaks in Java

For any developer, memory should be one of the most precious resources to think of while writing a program. A program can be said to be memory efficient when it consumes as little memory as possible when in operation but still doing what it was designed to do. So, before write code think of memory uses, do you know What happens when a Java object is created?

What is a Memory Leak?

In simple words, memory leak means unused memory that the garbage collectors can not reclaim.

A memory leak occurs when objects are no longer being used by the application, but the garbage collector is unable to clear them from working memory. This is a serious problem because these objects hold the memory that could otherwise be used by other parts of the program. With time, this piles up and leads to a degradation in system performance over time.

Garbage Collection in Java

One of the coolest features of Java is its automatic memory management. The Garbage Collection is a program that implicitly takes care of memory allocation and deallocation. It’s an effective program and can handle the majority of memory leaks that are likely to occur. However, it’s not infallible. Memory leaks can still sneak up and start taking up precious resources and, in worst cases, result in the java.lang.OutOfMemoryError.

It’s worth mentioning that an OutOfMemoryError is not always because of memory leaks. At times, it could be poor code practices like loading large files in memory.

The three common causes of memory leaks?

  • Misused static fields
  • Un closed streams
  • Un closed connections

Misused static fields

Static fields live in the memory as long as the class that owns them is loaded in the JVM, which means there are no instances of the class in the JVM, at this point, the class will be unloaded and the static field will be marked for garbage collection. But the catch here is, the static classes can live in the memory forever.

Consider the following code:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class StaticDemo {
public static List&lt;Integer&gt; list = new ArrayList&lt;&gt;();

public void populateList() {
for (int i = 0; i &lt; 10000000; i++) {
   list.add(new Random().nextInt());
}
}
public static void main(String[] args) {
  new StaticDemo().populateList();
}
}

This is a simple and small code snippet, we have a static List and we added values into it. But If we see the declaration of the list we have used static in front of it.  That’s the problem, the memory occupied by this list will be in use until the program finishes its execution even though the operations on the list are already completed.

To avoid this mistake, Minimize the use of static fields in your application.

Un closed streams

Till now we have understood memory leak is when code holds a reference to an object and the garbage collector can’t claim that object. But, a closed stream object is not memory unless it holds a reference of an unclosed stream.

Usually, the operating system limits how many open files (while using FileInputStream) an application can have. So, if such streams are not closed and the garbage collector may take some to claim these objects, it is also a case of the leak but not particularly a memory leak.

Refer to the following code snippet:

import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;

public class OpenStreamDemo {

    public static void main(String[] args) throws IOException {
        URL url = new URL("http://ergast.com/api/f1/2004/1/results.json");
        ReadableByteChannel rbc = Channels.newChannel(url.openStream());
        FileOutputStream outputStream = new FileOutputStream("/");
        outputStream.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
    }
}

Here the unclosed FileOutputStream and ReadableByteChannel will cause potential issues. The solution to this problem would be closing these stream objects once they are used and not require further. Or use java to try with resources wherever allowed.

rbc.close();
outputStream.close();

Un closed connections

The frequent mistake in Java programming is, developer forgot to close the database connections.  Having an unclosed database connection can give you a tough time in production and they are difficult to replicate in local environments.

Refer to the below code snippet:

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class OpenConnectionDemo {

    public static void main(String[] args) {
        try {
            List&lt;String&gt; names = fetchUsersName("foo", "bar");
            names.forEach(System.out::println);

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static List&lt;String&gt; fetchUsersName(String username, String password) throws SQLException {
        List&lt;String&gt; names = new ArrayList&lt;&gt;();
        Connection con = DriverManager.getConnection("jdbc:myDriver:devDB",
                username,
                password);

        Statement stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT first_name, last_name FROM users");

        String firstName = "";
        String lastName = "";

        while (rs.next()) {
            firstName = rs.getString("first_name");
            lastName = rs.getString("last_name");
            names.add(firstName + " " + lastName);
        }
        return names;
    }
}

Here every resource is leaking. Here we could have use try-catch and finally, and inside the finally block we can close

stmt.close();
con.close();

Here is the complete code for the fetchUsersName method.

public static List&lt;String&gt; fetchUsersName(String username, String password) throws SQLException {
    Statement stmt = null;
    Connection con = null;
    List&lt;String&gt; names = new ArrayList&lt;&gt;();
    try {

        con = DriverManager.getConnection("jdbc:myDriver:devDB",
                username,
                password);

        stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT first_name, last_name FROM users");

        String firstName = "";
        String lastName = "";

        while (rs.next()) {
            firstName = rs.getString("first_name");
            lastName = rs.getString("last_name");
            names.add(firstName + " " + lastName);
        }
    }catch (SQLException se){
        se.printStackTrace();
    }finally {
        stmt.close();
        con.close();
    }
    return names;
}

Or we can use try with resources like below.

public static List&lt;String&gt; fetchUsersName(String username, String password) throws SQLException {
    List&lt;String&gt; names = new ArrayList&lt;&gt;();
    try (Connection con = DriverManager.getConnection("jdbc:myDriver:devDB",username,password);
         Statement stmt = con.createStatement();
    ){
        ResultSet rs = stmt.executeQuery("SELECT first_name, last_name FROM users");

        String firstName = "";
        String lastName = "";

        while (rs.next()) {
            firstName = rs.getString("first_name");
            lastName = rs.getString("last_name");
            names.add(firstName + " " + lastName);
        }
    }catch (SQLException se){
        se.printStackTrace();
    }
    return names;
}

We can also use ORM like hibernate or jooq which provides easier and more maintainable resource handling.

So the take away from this post are:

  1. Be careful while using static fields.
  2. Make sure to close the stream and connection or use try with resources.
  3. Use ORM if your application allows.

 

Happy Learning !!!

Parsing JSON With Java 8 Without Dependencies

While working with JSON we often need to parse the JSON into an object, or Map, or List, or to a custom object as well.  To parse the JSON we have to use a dependency to process it easily.

But, starting with JDK 8u60+ the built-in Nashorn engine is capable to convert JSON content into java.util.Map or java.util.List. No external dependencies are required for parsing.

Here is an example with sample JSON. You can follow the below steps.

  1. Copy the below JSON into a file “test.json” and place it inside your java project.
{
	"page": "1",
	"per_page": 10,
	"total": 23,
	"total_pages": 3,
	"data": [
		{
			"competition": "UEFA Champions League",
			"year": 2014,
			"round": "GroupG",
			"team1": "Chelsea",
			"team2": "Schalke 04",
			"team1goals": "1",
			"team2goals": "1"
		},
		{
			"competition": "UEFA Champions League",
			"year": 2014,
			"round": "GroupG",
			"team1": "Chelsea",
			"team2": "NK Maribor",
			"team1goals": "6",
			"team2goals": "0"
		},
		{
			"competition": "UEFA Champions League",
			"year": 2014,
			"round": "GroupG",
			"team1": "Chelsea",
			"team2": "Sporting CP",
			"team1goals": "3",
			"team2goals": "1"
		},
		{
			"competition": "UEFA Champions League",
			"year": 2014,
			"round": "R16",
			"team1": "Chelsea",
			"team2": "Paris Saint-Germain",
			"team1goals": "1",
			"team2goals": "1"
		},
		{
			"competition": "English Premier League",
			"year": 2014,
			"round": "",
			"team1": "Chelsea",
			"team2": "Leicester City",
			"team1goals": "2",
			"team2goals": "0"
		},
		{
			"competition": "English Premier League",
			"year": 2014,
			"round": "",
			"team1": "Chelsea",
			"team2": "Swansea City",
			"team1goals": "4",
			"team2goals": "2"
		},
		{
			"competition": "English Premier League",
			"year": 2014,
			"round": "",
			"team1": "Chelsea",
			"team2": "Aston Villa",
			"team1goals": "3",
			"team2goals": "0"
		},
		{
			"competition": "English Premier League",
			"year": 2014,
			"round": "",
			"team1": "Chelsea",
			"team2": "Arsenal",
			"team1goals": "2",
			"team2goals": "0"
		},
		{
			"competition": "English Premier League",
			"year": 2014,
			"round": "",
			"team1": "Chelsea",
			"team2": "Queens Park Rangers",
			"team1goals": "2",
			"team2goals": "1"
		},
		{
			"competition": "English Premier League",
			"year": 2014,
			"round": "",
			"team1": "Chelsea",
			"team2": "West Bromwich Albion",
			"team1goals": "2",
			"team2goals": "0"
		}
	]
}

2. Create a class “JSONParser.java” and put the below code inside it.

package com.codersdesks.json;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.junit.Before;
import org.junit.Test;

public class JSONParser {
	
	private ScriptEngine scriptEngine;
	private String json;

	@Before
	public void setup() throws IOException {
		ScriptEngineManager sem = new ScriptEngineManager();
		this.scriptEngine = sem.getEngineByName("javascript");
		File file = new File("test.json");
		this.json = new String(Files.readAllBytes(file.toPath()));
	}

	@Test
	public void parse() throws ScriptException {
		String script = "Java.asJSONCompatible(" + this.json + ")";
		Object result = this.scriptEngine.eval(script);
		Map contents = (Map) result;
		
		contents.forEach((k,v) ->{
			System.out.println("Key => "+k +" value =>"+contents.get(k));
		});
		
		List data = (List) contents.get("data");
		data.forEach(d ->{
			Map matchDetail = (Map) d;
			matchDetail.forEach((k,v) ->{
				System.out.println("Key => "+k +" value =>"+matchDetail.get(k));
			});	
		});
	}

}

Run the Junit test and you can see the below output.

Key => page value =>1
Key => per_page value =>10
Key => total value =>23
Key => total_pages value =>3
Key => data value =>[[object Object], [object Object], [object Object], [object Object], [object Object], [object Object], [object Object], [object Object], [object Object], [object Object]]
Key => competition value =>UEFA Champions League
Key => year value =>2014
Key => round value =>GroupG
Key => team1 value =>Chelsea
Key => team2 value =>Schalke 04
Key => team1goals value =>1
Key => team2goals value =>1
Key => competition value =>UEFA Champions League
Key => year value =>2014
Key => round value =>GroupG
Key => team1 value =>Chelsea
Key => team2 value =>NK Maribor
Key => team1goals value =>6
Key => team2goals value =>0
Key => competition value =>UEFA Champions League
Key => year value =>2014
Key => round value =>GroupG
Key => team1 value =>Chelsea
Key => team2 value =>Sporting CP
Key => team1goals value =>3
Key => team2goals value =>1
Key => competition value =>UEFA Champions League
Key => year value =>2014
Key => round value =>R16
Key => team1 value =>Chelsea
Key => team2 value =>Paris Saint-Germain
Key => team1goals value =>1
Key => team2goals value =>1
Key => competition value =>English Premier League
Key => year value =>2014
Key => round value =>
Key => team1 value =>Chelsea
Key => team2 value =>Leicester City
Key => team1goals value =>2
Key => team2goals value =>0
Key => competition value =>English Premier League
Key => year value =>2014
Key => round value =>
Key => team1 value =>Chelsea
Key => team2 value =>Swansea City
Key => team1goals value =>4
Key => team2goals value =>2
Key => competition value =>English Premier League
Key => year value =>2014
Key => round value =>
Key => team1 value =>Chelsea
Key => team2 value =>Aston Villa
Key => team1goals value =>3
Key => team2goals value =>0
Key => competition value =>English Premier League
Key => year value =>2014
Key => round value =>
Key => team1 value =>Chelsea
Key => team2 value =>Arsenal
Key => team1goals value =>2
Key => team2goals value =>0
Key => competition value =>English Premier League
Key => year value =>2014
Key => round value =>
Key => team1 value =>Chelsea
Key => team2 value =>Queens Park Rangers
Key => team1goals value =>2
Key => team2goals value =>1
Key => competition value =>English Premier League
Key => year value =>2014
Key => round value =>
Key => team1 value =>Chelsea
Key => team2 value =>West Bromwich Albion
Key => team1goals value =>2
Key => team2goals value =>0

You can also read about JSON Schema and How to use Jackson databind with JSON

For more information, you can refer to the official Nashorn extensions documentation.

Happy Learning !!

io.lettuce.core.RedisConnectionException: DENIED Redis is running in protected mode

Problem

While trying to connect to Redis running on Linux through my java code getting io.lettuce.core.RedisConnectionException: DENIED Redis is running in protected mode.

The exception stack trace is as below.

io.lettuce.core.RedisConnectionException: DENIED Redis is running in protected mode because the protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode, connections are only accepted from the loopback interface. If you want to connect from external computers to Redis you may adopt one of the following solutions: 1) Just disable protected mode sending the command 'CONFIG SET protected-mode no' from the loopback interface by connecting to Redis from the same host the server is running, however MAKE SURE Redis is not publicly accessible from internet if you do so. Use CONFIG REWRITE to make this change permanent. 2) Alternatively you can just disable the protected mode by editing the Redis configuration file, and setting the protected mode option to 'no', and
then restarting the server. 3) If you started the server manually just for testing, restart it with the '--protected-mode no' option. 4) Setup a bind address or an authentication password. NOTE: You only need to do one of the above things in order for the server to start accepting connections from the outside.
        at io.lettuce.core.protocol.CommandHandler.onProtectedMode(CommandHandler.java:667) ~[lettuce-core-5.0.1.RELEASE.jar!/:na]
        at io.lettuce.core.protocol.CommandHandler.channelInactive(CommandHandler.java:305) ~[lettuce-core-5.0.1.RELEASE.jar!/:na]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:245) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:231) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:224) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:75) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.lettuce.core.ChannelGroupListener.channelInactive(ChannelGroupListener.java:46) ~[lettuce-core-5.0.1.RELEASE.jar!/:na]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:245) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:231) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:224) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.channel.ChannelInboundHandlerAdapter.channelInactive(ChannelInboundHandlerAdapter.java:75) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.lettuce.core.PlainChannelInitializer$1.channelInactive(PlainChannelInitializer.java:85) ~[lettuce-core-5.0.1.RELEASE.jar!/:na]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:245) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:231) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:224) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1429) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:245) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:231) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Fina
l]
        at io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:947) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:822) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) ~[netty-common-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404) ~[netty-common-4.1.31.Final.jar!/:4.1.31.Final]
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:466) ~[netty-transport-4.1.31.Final.jar!/:4.1.31.Final]

Solution

After analyzing the logs noticed following lines which describe the root cause and fix for this.

DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no auth

In order to fix this we need to do one of the following:

  1. Disable protected mode from redis CLI
  2. Disable protected mode from redis config
  3. Restart redis it with the ‘–protected-mode no’ option, only for testing purposes.
  4. Setup a bind address or an auth

Since we knew the solution for this, let’s see how we can actually do it.

  1. To disable the protected mode just open the redis-cli and run ‘CONFIG SET protected-mode no’.
  2. To disable the protected mode stop redis server and edit redis.conf file inside conf folder, add ‘protected-mode no’.  Restart the redis server .
  3. To restart redis server with –protected-mode no’ option, run redis-server  with option –protected-mode. Like redis-server –protected-mode no
  4. To bind an IP address stop redis server, edit redis config and add bind *.*.*.* to bind a specific IP to access the redis server. i.e. bind 127.0.0.1. Restart redis server.

Note: If none of the above options are performed you will not be able to access redis server.

If you know of any other fixes to this issue please let us know through comments.

Read more about Java

What happens when a Java object is created?

Java 8 Stream API with examples

Happy Learning !!

Amazon EC2 – disk full /dev/nvme0n1p1 full how to fix

Problem: While running my Jenkins build, build failed with following error.

[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.1.RELEASE:repackage (repackage) on project <project name>: No space left on device -> [Help 1]

To investigate, when I run df -h on my Amazon EC2 server, this is the output:

[root@ip-172-*-*-3 builds]# df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 1.9G 516K 1.9G 1% /run
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/nvme0n1p1 20G 20G 76K 100% /
tmpfs 389M 0 389M 0% /run/user/1000

For some reason my space is almost full and I really can’t find the big files or directory is easily.

To get the files/directory eating up my space I used the following command to find all the files greater than 10 MB:

sudo find / -type f -size +10M -exec ls -lh {} \;

This command return you list of files with complete path, which helps me to identify which ones are causing the trouble and deal with them accordingly.

After analyzing the result form the above command, I found that Jenkins keeps archiving all the previous builds which are eating up most of my memory.

Once I have the list of files I deleted all the large files using rm -r commands and removed all the files inside directory using rm -rf *.

Once I have deleted the large files, I ran the Jenkins build again and it work perfectly.

So, while using Jenkins I think we should also think about the clean up process for the archives, if not the entire one we can delete the significantly old archives and have enough space for builds to execute successfully.

Read more about Java here.

 

MongoDB CRUD operations in detail

In the previous post, we discussed the fundamentals of MongoDB and also introduced you to MongoDB CRUD operations. In this post we will deep dive into CRUD operations as often we use them only.

Here is the list of methods provided by MongoDB to fulfill the requirement of CRUD operations.

InsertFindUpdateDelete
insertOne()findOne()updateOne()deleteOne()
insertMany()find()UpdateMany()deleteMany()
insert()findAndModify()Update()remove()
findOneAndDelete()replaceOne()
findOneAndReplace()
findOneAndUpdate()

Let’s move further and discuss each of the methods in detail.

Create

The first operation of CRUD used to create new documents in a collection. As shown in the above table MongoDB offers three methods to create new documents. These three methods use the default write concern unless we pass a write concern and likewise the use database command it also creates a new collection if the collection is not available.

db.collection.insertOne() inserts a single document into a collection.

Syntax:

db.collection.insertOne(
   <document>,
   {
      writeConcern: <document>
   }
)

Returns: A document containing:

  • A boolean acknowledged as true if the operation ran with write concern or false if write concern was disabled.
  • A field inserted Id with the _id value of the inserted document.

In the below example we will insert a new document in userinfo collection. Make sure you are in the correct database. To use a database just write

use this command does two things, one creates a new database if it does not exist, and switch to the given database.

use user
switched to db user
db.userinfo.insertOne({name:'user 1',email:'user1@test.com',age:21})

#Output 
{
"acknowledged" : true,
"insertedId" : ObjectId("5ed6f5a9b66c8269070b4af2")
}

db.collection.insertMany() can insert multiple documents into a collection. This method takes an array of documents.

Syntax:

db.collection.insertMany(
   [ <document 1> , <document 2>, ... ],
   {
      writeConcern: <document>,
      ordered: <boolean>
   }
)

The ordered boolean parameter is Optional also as mentioned above it uses default concern if not provided. A boolean specifying whether the mongo instance should perform an ordered or unordered insert. Defaults to true.

Returns: A document containing:

  • A boolean acknowledged as true if the operation ran with write concern or false if write concern was disabled
  • An array of _id for each successfully inserted documents

Refer to the below snippet here we have created 3 documents using insert many.

db.userinfo.insertMany([

{name:'user 2',email:'user2@test.com',age:22},

{name:'user 3',email:'user3@test.com',age:32},

{name:'usr 4',email:'user4@test.com',age:30}

])

#Output 

{


"acknowledged" : true,
"insertedIds" : [
ObjectId("5ed6f6ceb66c8269070b4af3"),
ObjectId("5ed6f6ceb66c8269070b4af4"),
ObjectId("5ed6f6ceb66c8269070b4af5")
]
}

db.collection.insert() Inserts a document or documents into a collection. It works as insertOne () in case of a single document and in case of multiple documents works as insertMany ().

Syntax:

db.collection.insert(
   <document or array of documents>,
   {
     writeConcern: <document>,
     ordered: <boolean>
   }
)

Returns:

  • A WriteResult object for single inserts.
  • A BulkWriteResult object for bulk inserts.

MongoDB also provide  db.collection.save() method to create documents but as per the Mongo documentation it is deprecated and they emphasize on using inserOne (), insertMany() and insert() methods.

Read

The second operation of CRUD used to read/fetch the documents from a collection. As shown in the above table MongoDB offers two methods to fetch the data from a collection.

db.collection.findOne() Returns one document that satisfies the specified query criteria on the collection or the first document from the collections if no query provided.

Syntax:

db.collection.findOne(query, projection)

Parameter

query:  The query parameter is an Optional document, which specifies a query for selection criteria using query operators.

projection: It is also an Optional document, which specifies the fields to return using projection operators. Omit this parameter to return all fields in the matching document. For details, see Projection.

Note: The basic thumb rule for applying projection is to use 1 to include any field and 0 to exclude. By default, the _id field is always included unless you explicitly exclude it.

Returns:

It returns One document that matches the criteria specified in the query, the first parameter. If you specify a projection parameter, findOne() returns a document that only contains the projection fields.

Although it is similar to the find() method, the findOne() method returns a document rather than a cursor.

Example:

db.employees.findOne({gender:'male'},{gender:1, name:1})

#Output

{
"_id" : ObjectId("5f20577536c73fc3e870fda4"),
"gender" : "male",
"name" : {
"title" : "mr",
"first" : "harvey",
"last" : "chambers"
}
}

db.collection.find() Returns document or documents that satisfies the specified query criteria on the collection.

Syntax:

db.collection.find(query, projection)

Parameter

query:  The query parameter is an Optional document, which specifies a query for selection criteria using query operators.

projection: It is also an Optional document, which specifies the fields to return using projection operators. Omit this parameter to return all fields in the matching document. For details, see Projection.

Returns:

It returns the document or documents that match the criteria specified in the query. If you specify a projection parameter, find () returns a document that only contains the projection fields.

Although it is similar to the findOne() method, the find() method returns a cursor instead of documents.

Example:

db.employees.find({},{gender:1, name:1})db.employees.findOne({gender:'male'},{gender:1, name:1})

#Output


> db.employees.find({},{gender:1, name:1})
{ "_id" : ObjectId("5f20577536c73fc3e870fda4"), "gender" : "male", "name" : { "title" : "mr", "first" : "harvey", "last" : "chambers" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fda5"), "gender" : "male", "name" : { "title" : "mr", "first" : "victor", "last" : "pedersen" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fda6"), "gender" : "male", "name" : { "title" : "mr", "first" : "elijah", "last" : "lewis" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fda7"), "gender" : "female", "name" : { "title" : "mrs", "first" : "olav", "last" : "oehme" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fda8"), "gender" : "male", "name" : { "title" : "mr", "first" : "carl", "last" : "jacobs" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fda9"), "gender" : "female", "name" : { "title" : "mrs", "first" : "madeleine", "last" : "till" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdaa"), "gender" : "female", "name" : { "title" : "miss", "first" : "shona", "last" : "kemperman" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdab"), "gender" : "female", "name" : { "title" : "ms", "first" : "louise", "last" : "graham" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdac"), "gender" : "male", "name" : { "title" : "mr", "first" : "zachary", "last" : "lo" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdad"), "gender" : "male", "name" : { "title" : "mr", "first" : "isolino", "last" : "viana" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdae"), "gender" : "female", "name" : { "title" : "mrs", "first" : "katie", "last" : "welch" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdaf"), "gender" : "female", "name" : { "title" : "miss", "first" : "sandra", "last" : "lorenzo" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb0"), "gender" : "female", "name" : { "title" : "miss", "first" : "mestan", "last" : "kaplangı" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb2"), "gender" : "male", "name" : { "title" : "mr", "first" : "gideon", "last" : "van drongelen" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb3"), "gender" : "female", "name" : { "title" : "miss", "first" : "maeva", "last" : "wilson" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb4"), "gender" : "female", "name" : { "title" : "ms", "first" : "anaëlle", "last" : "adam" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb5"), "gender" : "female", "name" : { "title" : "miss", "first" : "anne", "last" : "ruiz" } }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb6"), "gender" : "female", "name" : { "title" : "mademoiselle", "first" : "delia", "last" : "durand" } }
Type "it" for more
>

db.collection.findAndModify() Used to modifies and return a single document. By default, the returned document does not include the modifications made on the update. To return the updated document, we need to use the new option.

Syntax:

db.collection.findAndModify({
    query: <document>,
    sort: <document>,
    remove: <boolean>,
    update: <document or aggregation pipeline>,
    new: <boolean>,
    fields: <document>,
    upsert: <boolean>,
    bypassDocumentValidation: <boolean>,
    writeConcern: <document>,
    collation: <document>,
    arrayFilters: [ <filterdocument1>, ... ]
});

 

query:  The query parameter is an Optional document, which specifies a query for selection criteria using query operators similar to find() method. Although the query may match multiple documents, db.collection.findAndModify() will only select one document to modify.

sort: It is also an Optional document, determines which document the operation modifies if the query selects multiple documents. db.collection.findAndModify() modifies the first document in the sort order specified by this argument.

remove: An optional field of type boolean which must specify either to remove or update the field. Removes the document specified in the query field. Set this to true to remove the selected document. The default is false.

new: An optional boolean field. When true, returns the modified document rather than the original. The db.collection.findAndModify() method ignores the new option for remove operations. The default is false.

fields: An Optional document work similar to projection in find() method. The fields document specifies an inclusion of a field with 1, as in: fields: { : 1, : 1, … }.

For more details on parameter visit Mongo official doc

Returns:

To remove operations, if the query matches a document, it will return the removed document. If the query does not match a document to remove returns null.

For update operations, it will return one of the following:

If the new parameter is not set or is false:

  • The pre-modification document is returned if the query matches a document
  • Otherwise, null.

If new is set to true:

  • The modified document if the query returns a match
  • The inserted document if upsert: true and no document matches the query
  • Otherwise, null

Example:

db.userinfo.find({name:'test user'})

#Output

{ "_id" : ObjectId("5f444629c2254dfb46403a0a"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f4446c9c2254dfb46403a0b"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }


db.userinfo.findAndModify({
query: {name:'test user'},
update: { age: 22}
})

#Output

{
"_id" : ObjectId("5f444629c2254dfb46403a0a"),
"name" : "test user",
"email" : "testuser@test.com",
"age" : 21
}

Here you can see that it updated the document successfully but returned the old one with age 21.

If we again run the following query we will get the updated document with age 22.

db.userinfo.find({name:'test user'})

#Output

db.userinfo.find({name:'test user'})
{ "_id" : ObjectId("5f4448cbc2254dfb46403a0c"), "name" : "test user", "email" : "testuser@test.com", "age" : 22 }
{ "_id" : ObjectId("5f4448cdc2254dfb46403a0d"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }

But, if we run the same update with one additional parameter new with the value true it will return the update document.

db.userinfo.findAndModify({
query: {name:'test user'},
update: {name:'test user',email:'testuser@test.com',age:23},
new :true
})

#Output

{
"_id" : ObjectId("5f4448cbc2254dfb46403a0c"),
"name" : "test user",
"email" : "testuser@test.com",
"age" : 23
}

db.collection.findOneAndDelete() Used to deletes a single document based on the filter and sort criteria, returning the deleted document. Deletes the first matching document in the collection that matches the filter. The sort parameter can be used to influence which document is deleted.

Syntax:

db.collection.findOneAndDelete(
   <filter>,
   {
     projection: <document>,
     sort: <document>,
     maxTimeMS: <number>,
     collation: <document>
   }
)

Parameter

filter: The selection criteria for the deletion same as the query in find() method. Pass and empty {} document to delete the first document returned in the collection. By default, an empty document {}.

projection: Same as the projection in find() method

sort: An Optional field. Specifies a sorting order for the documents matched by the filter.

For more details on parameter visit Mongo official doc

Returns: Returns the deleted document.

Example:

db.userinfo.find({name:'test user'})
{ "_id" : ObjectId("5f4448cbc2254dfb46403a0c"), "name" : "test user", "email" : "testuser@test.com", "age" : 23 }
{ "_id" : ObjectId("5f4448cdc2254dfb46403a0d"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }

#Output

db.userinfo.findOneAndDelete({age:23})
{
"_id" : ObjectId("5f4448cbc2254dfb46403a0c"),
"name" : "test user",
"email" : "testuser@test.com",
"age" : 23
}

Now if run the same find command again we will only get a single record with name ‘test user’

db.userinfo.find({name:'test user'})
{ "_id" : ObjectId("5f4448cdc2254dfb46403a0d"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }

db.collection.findOneAndReplace() Used to replace a single document based on the specified filter. The sort parameter can be used to influence which document is deleted. It works the same way findAndModify() works.

Syntax:

db.collection.findOneAndReplace( 
	<filter>, <replacement>, 
	{ projection: <document>,
	 sort: <document>, 
	 maxTimeMS: <number>,
	 upsert: <boolean>, 
	 returnNewDocument: <boolean>,
	 collation: <document> 
	} 
)

Parameter

filter: The selection criteria for the deletion same as the query in find() method. Pass and empty {} document to delete the first document returned in the collection. By default, an empty document {}.

replacement: The replacement document.

projection: Same as the projection in find() method

sort: An Optional field. Specifies a sorting order for the documents matched by the filter.

returnNewDocument: An Optional field. When true, returns the replacement document instead of the original document. Defaults to false.

For more details on parameter visit Mongo official doc

Returns: Returns either the original document or the replaced document if returnNewDocument is true.

Example:

db.userinfo.find({name:'test user'})

#Output

{ "_id" : ObjectId("5f4448cdc2254dfb46403a0d"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbcc2254dfb46403a0e"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a0f"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a10"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }

db.userinfo.findOneAndReplace(
{ "age" : 21},
{name:'test user',email:'testuserAge22@test.com',age:22}
)


#Output

{
"_id" : ObjectId("5f4448cdc2254dfb46403a0d"),
"name" : "test user",
"email" : "testuser@test.com",
"age" : 21
}

db.userinfo.find({name:'test user'})

#Output

{ "_id" : ObjectId("5f4448cdc2254dfb46403a0d"), "name" : "test user", "email" : "testuserAge22@test.com", "age" : 22 }
{ "_id" : ObjectId("5f444fbcc2254dfb46403a0e"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a0f"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a10"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }

But, if we pass returnNewDocument as true, it will return the replaced document.

db.userinfo.findOneAndReplace(
{ "age" : 22},
{name:'test user',email:'testuserAge23@test.com',age:23},
{returnNewDocument : true}
)

#Output
{
"_id" : ObjectId("5f4448cdc2254dfb46403a0d"),
"name" : "test user",
"email" : "testuserAge23@test.com",
"age" : 23
}

db.collection.findOneAndUpdate() Used to update a single document based on the filter and sort criteria.

Used to replace a single document based on the specified filter. The sort parameter can be used to influence which document is deleted. It works the same way findAndModify() works.

Syntax:

db.collection.findOneAndUpdate(
   <filter>,
   <update document or aggregation pipeline>,
   {
     projection: <document>,
     sort: <document>,
     maxTimeMS: <number>,
     upsert: <boolean>,
     returnNewDocument: <boolean>,
     collation: <document>,
     arrayFilters: [ <filterdocument1>, ... ]
   }
)

Parameter

filter: The selection criteria for the deletion same as the query in find() method. Pass and empty {} document to delete the first document returned in the collection. By default, an empty document {}.

update: The updated document.

projection: Same as the projection in find() method

sort: An Optional field. Specifies a sorting order for the documents matched by the filter.

returnNewDocument: An Optional field. When true, returns the replacement document instead of the original document. Defaults to false.

For more details on parameter visit Mongo official doc

Returns: Returns either the original document or the replaced document if returnNewDocument is true.

Example:
db.userinfo.find({name:'test user'})

#output

{ "_id" : ObjectId("5f4448cdc2254dfb46403a0d"), "name" : "test user", "email" : "testuserAge23@test.com", "age" : 23 }
{ "_id" : ObjectId("5f444fbcc2254dfb46403a0e"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a0f"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a10"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }

db.userinfo.findOneAndUpdate(
{ "age" : 23},
{ $inc: { "age" : 2 }},
{returnNewDocument : true}
)

#output

{
"_id" : ObjectId("5f4448cdc2254dfb46403a0d"),
"name" : "test user",
"email" : "testuserAge23@test.com",
"age" : 25
}

db.userinfo.find({name:'test user'})

#output

{ "_id" : ObjectId("5f4448cdc2254dfb46403a0d"), "name" : "test user", "email" : "testuserAge23@test.com", "age" : 25 }
{ "_id" : ObjectId("5f444fbcc2254dfb46403a0e"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a0f"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }
{ "_id" : ObjectId("5f444fbec2254dfb46403a10"), "name" : "test user", "email" : "testuser@test.com", "age" : 21 }

Note: The update parameter only contains update operator expressions.  You can not pass an entire document to replace as we did in the findOneAndReplace() method.

 

IntelliJ: Error:java: error: release version 5 not supported

Problem: While creating a new maven project using IntelliJ IDEA with Java 11 started getting the following error:

Error:java: error: release version 5 not supported

After exploring the internet for a while I found what is causing this error.

Reason: Generally Maven sets the default Java version to 1.5. Hence you need to set the correct language level and release version in pom.xml.

Before searching for a solution you can check your current Java version at, File => Settings => Build, Execution, Deployment => Compiler => Java Compiler and change it if required.

IntelliJ_Java_compiler_version

Even after changing the java version, if it didn’t work, you can apply the following solutions.

Solution 1:

Set the source /target versions in pom.xml like below:

<properties>
     <maven.compiler.source>1.11</maven.compiler.source>
     <maven.compiler.target>1.11</maven.compiler.target>
</properties>

You will also need to include the maven-compiler-plugin if you haven’t already like:

plugins>
     <plugin>
	 <groupId>org.apache.maven.plugins</groupId>
	      <artifactId>maven-compiler-plugin</artifactId>
	      <version>3.6.0</version>
	      <configuration>
	        <source>1.11</source>
                <target>1.11</target>
	      </configuration>
	</plugin>
</plugins>

Solution 2: Specific to SPring boot, If you are using spring boot as a parent, you have to set the java version.

<properties>
   <java.version>11</java.version>
</properties>

This will automatically set the correct versions.

If The above-mentioned option didn’t work for you, you can move one step further by changing the “language level” in every module at, File => Project Structure => Modules

Here we discussed how we can change the Java compiler version in IntelliJ and solution to common error while creating a maven project using IntelliJ.

You are free to share if there are other ways to fix this error.

If you are new to Java you may find these articles helpful.

What happens when a Java object is created?

Java bitwise operators with example

Java Exception in detail with example

How to create Java Custom Exception?

Java try with resources statement

Java Generic, Generic with super and wildcard

Happy Learning !!

Mongodb find by id, findone, find in array, find like, find limit, find count, Mongodb projection

Introduction

In the real-world application, we use a database to store the data be it a relational database or any NoSQL database. Apart from storing the data, we need to retrieve the data well. Querying the data is very important in terms of performance and memory uses. It is a good idea to fetch the relevant data only, as loading the unnecessary data will cause a performance hit as well as additional memory uses.

Mongodb

There can multiple requirements to fetch the data, in this post I will explain the following ways to fetch the data in MongoDB.

  • Mongodb find by id
  • Mongodb findone
  • Mongodb find
  • Mongodb find with limit
  • Mongodb Sort
  • Mongodb Projection
  • Mongodb find count
  • Mongodb findone latest
  • Mongodb find like
  • Mongodb find in array
  • Mongodb cursor to toArray

I have created a database company and created a collection of employees inside it and I will use the same database and collection in the entire post. You can download the sample employees’ data file from here. You can import this sample file in MongoDB using the below commands from Mongo Shell. If you are not familiar with Mongo Shell, you can check my previous post on Setting up MongoDB and an introduction to the shell.

mongoimport employees.json -d company -c employees --jsonArray

-d is the name of the database

-c is the name of the collection

If the JSON file is an array pass -–jsonArray

If you want to drop the database if it exists pass -–drop in the above command

Mongodb find

Mongodb find by id

In Mongodb, every document inside a collection will have a primary key that is denoted by _id. It is an ObjectID, one of the BSON data types of MongoDB, using this record inside a collection can be differentiated. Also, Mongodb automatically indexed this. 

As it holds a unique value for each document, we can fetch that particular document using this. Let’s check it with an example. 

Let’s fetch the employee having id ObjectId(“5f20577536c73fc3e870fda3”), run the following command to fetch it. You can use pretty() to print the output in more readable format.

Command: db.collectionName.find({_id : })

Example: db.employees.find({_id:ObjectId(“5f20577536c73fc3e870fdb6”)})

With pretty print

Command: db.collectionName.find({_id : }).pretty()

Example: db.employees.find({_id:ObjectId(“5f20577536c73fc3e870fdb6”)}).pretty()

 db.employees.find({_id: ObjectId("5f20577536c73fc3e870fdb6")}).pretty()
{
        "_id" : ObjectId("5f20577536c73fc3e870fdb6"),
        "gender" : "female",
        "name" : {
                "title" : "mademoiselle",
                "first" : "delia",
                "last" : "durand"
        },
        "location" : {
                "street" : "6735 rue abel-hovelacque",
                "city" : "fontaines-sur-grandson",
                "state" : "appenzell ausserrhoden",
                "postcode" : 6137,
                "coordinates" : {
                        "latitude" : "-65.0877",
                        "longitude" : "-90.4049"
                },
                "timezone" : {
                        "offset" : "+2:00",
                        "description" : "Kaliningrad, South Africa"
                }
        },
        "email" : "delia.durand@example.com",
        "login" : {
                "uuid" : "6c4ea050-eca4-4809-8024-96a98f655553",
                "username" : "purplebear663",
                "password" : "sparky1",
                "salt" : "rzU1EPXV",
                "md5" : "a9198f953f34daf7b461b6065734d13b",
                "sha1" : "43c50f99742937b3ddd3f9ec0863924741b408c9",
                "sha256" : "63da5442d2a4d2ca02e0b3bb138e28760aa732258e35de102c8fd652c48721ea"
        },
        "dob" : {
                "date" : "1966-08-03T09:22:41Z",
                "age" : 52
        },
        "registered" : {
                "date" : "2009-05-28T19:09:24Z",
                "age" : 9
        },
        "phone" : "(166)-728-8912",
        "cell" : "(301)-529-4162",
        "id" : {
                "name" : "AVS",
                "value" : "756.5746.5832.39"
        },
        "picture" : {
                "large" : "https://randomuser.me/api/portraits/women/91.jpg",
                "medium" : "https://randomuser.me/api/portraits/med/women/91.jpg",
                "thumbnail" : "https://randomuser.me/api/portraits/thumb/women/91.jpg"
        },
        "nat" : "CH"
}

Mongodb findone

The findOne() method Return the single document if the filter is passed it will get the matching first document if not it will return the first document from the collection.

Command: db.collectionName.findOne()

Example: db.employees.findOne()

Mongodb find

The find() returns a cursor object that points to any documents that match the specified query filters. Using the cursor object, we can further manipulate the result.  Like limiting and sorting the data, converting the result into the array and iterates the cursor, and returns a Promise that resolves to the next document in the cursor. If the cursor is exhausted, the promise resolves to undefine.

Command: db.collectionName.find()

Example: db.employees.find()

When you run the above commands, you can see Type “it” for more at the end of the result if there is enough data. If you type it, it will fetch the next set of data from the database.

Mongodb find with limit

The limit () is used to specify the maximum number of documents to fetch in the query result set. If the result set contains more documents than the specified limit, the cursor will return documents in order up to the limit.

Remember, you can’t call limit() method after retrieving one or more documents using cursor.next() or cursor.toArray().

Command: db.collectionName.find().limti()

Example: db.employees.find().limit(5)

 > db.employees.find().limit(4)

{ "_id" : ObjectId("5f20577536c73fc3e870fda4"), "gender" : "male", "name" : { "title" : "mr", "first" : "harvey", "last" : "chambers" }, "location" : { "street" : "3287 high street", "city" : "carlow", "state" : "wexford", "postcode" : 47671, "coordinates" : { "latitude" : "-22.5329", "longitude" : "168.9462" }, "timezone" : { "offset" : "+5:00", "description" : "Ekaterinburg, Islamabad, Karachi, Tashkent" } }, "email" : "harvey.chambers@example.com", "login" : { "uuid" : "8f583f57-c999-4a5d-a8c1-d913b574c082", "username" : "greenrabbit148", "password" : "june", "salt" : "dAsaXJGK", "md5" : "e3759db2391b798ffea2cc168e1280fd", "sha1" : "a3e77fd5fdd75e3b173ceec6c3c1bbe5e83540cc", "sha256" : "7564eac1899234d5902fadfb995303a58370232f54bee6adb26e25394e2ffddd" }, "dob" : { "date" : "1988-05-27T00:14:03Z", "age" : 30 }, "registered" : { "date" : "2007-03-11T06:20:19Z", "age" : 11 }, "phone" : "061-265-5188", "cell" : "081-146-8382", "id" : { "name" : "PPS", "value" : "5608572T" }, "picture" : { "large" : "https://randomuser.me/api/portraits/men/82.jpg", "medium" : "https://randomuser.me/api/portraits/med/men/82.jpg", "thumbnail" : "https://randomuser.me/api/portraits/thumb/men/82.jpg" }, "nat" : "IE" }
{ "_id" : ObjectId("5f20577536c73fc3e870fda5"), "gender" : "male", "name" : { "title" : "mr", "first" : "victor", "last" : "pedersen" }, "location" : { "street" : "2156 stenbjergvej", "city" : "billum", "state" : "nordjylland", "postcode" : 56649, "coordinates" : { "latitude" : "-29.8113", "longitude" : "-31.0208" }, "timezone" : { "offset" : "+5:30", "description" : "Bombay, Calcutta, Madras, New Delhi" } }, "email" : "victor.pedersen@example.com", "login" : { "uuid" : "fbb3c298-2cea-4415-84d1-74233525c325", "username" : "smallbutterfly536", "password" : "down", "salt" : "iW5QrgwW", "md5" : "3cc8b8a4d69321a408cd46174e163594", "sha1" : "681c0353b34fae08422686eea190e1c09472fc1f", "sha256" : "eb5251e929c56dfd19fc597123ed6ec2d0130a2c3c1bf8fc9c2ff8f29830a3b7" }, "dob" : { "date" : "1959-02-19T23:56:23Z", "age" : 59 }, "registered" : { "date" : "2004-07-07T22:37:39Z", "age" : 14 }, "phone" : "23138213", "cell" : "30393606", "id" : { "name" : "CPR", "value" : "506102-2208" }, "picture" : { "large" : "https://randomuser.me/api/portraits/men/23.jpg", "medium" : "https://randomuser.me/api/portraits/med/men/23.jpg", "thumbnail" : "https://randomuser.me/api/portraits/thumb/men/23.jpg" }, "nat" : "DK" }
{ "_id" : ObjectId("5f20577536c73fc3e870fda6"), "gender" : "male", "name" : { "title" : "mr", "first" : "elijah", "last" : "lewis" }, "location" : { "street" : "2623 paddock way", "city" : "virginia beach", "state" : "wyoming", "postcode" : 54880, "coordinates" : { "latitude" : "-42.6128", "longitude" : "-18.5996" }, "timezone" : { "offset" : "+3:30", "description" : "Tehran" } }, "email" : "elijah.lewis@example.com", "login" : { "uuid" : "2292b7c7-a9bf-4341-abbd-c5841444ab6e", "username" : "angrygorilla267", "password" : "toonarmy", "salt" : "DUtMcvWR", "md5" : "258eaa742373ee70976d53d1b84d4764", "sha1" : "62f168f38fa3f6efbd815b58518775d3c6cf0080", "sha256" : "a4ab496047b9de7df39adbdabfecc813b8da428087029c94c2b748cef092f85e" }, "dob" : { "date" : "1986-03-29T06:40:18Z", "age" : 32 }, "registered" : { "date" : "2007-12-24T10:32:11Z", "age" : 10 }, "phone" : "(187)-486-3727", "cell" : "(986)-974-0857", "id" : { "name" : "SSN", "value" : "127-66-9786" }, "picture" : { "large" : "https://randomuser.me/api/portraits/men/57.jpg", "medium" : "https://randomuser.me/api/portraits/med/men/57.jpg", "thumbnail" : "https://randomuser.me/api/portraits/thumb/men/57.jpg" }, "nat" : "US" }
{ "_id" : ObjectId("5f20577536c73fc3e870fda7"), "gender" : "female", "name" : { "title" : "mrs", "first" : "olav", "last" : "oehme" }, "location" : { "street" : "gartenstraße 64", "city" : "nastätten", "state" : "mecklenburg-vorpommern", "postcode" : 93640, "coordinates" : { "latitude" : "-52.8348", "longitude" : "-67.5738" }, "timezone" : { "offset" : "-3:00", "description" : "Brazil, Buenos Aires, Georgetown" } }, "email" : "olav.oehme@example.com", "login" : { "uuid" : "2608c05c-8951-4aee-bcd2-f598c80f32bb", "username" : "heavypeacock371", "password" : "silent", "salt" : "E6R29k0e", "md5" : "587f4392dc06a9fb69a52eae94fd32f2", "sha1" : "82eba68b1fe2407281da5787b9b89505c663b587", "sha256" : "304034638901015d8a7b2fd43530fffc4c7d621ccfab98de935d9c8387198796" }, "dob" : { "date" : "1960-11-28T23:07:18Z", "age" : 57 }, "registered" : { "date" : "2011-05-31T00:24:05Z", "age" : 7 }, "phone" : "0748-6607336", "cell" : "0176-5787554", "id" : { "name" : "", "value" : null }, "picture" : { "large" : "https://randomuser.me/api/portraits/women/6.jpg", "medium" : "https://randomuser.me/api/portraits/med/women/6.jpg", "thumbnail" : "https://randomuser.me/api/portraits/thumb/women/6.jpg" }, "nat" : "DE" }
>

Mongodb Sort

The sort() method of the cursor is used to sorts documents in the result set according to the sorting filter. Sort documents specify one or more fields to sort on. The value of each field indicates whether MongoDB should sort it in ascending (1) or descending (-1) order.

Command: db.collectionName.find().sort({ })

Example: db.employees.find().sort({_id:-1})

Mongodb Projection

Generally, the find() or findOne() method returns the entire document with the _id. But in some scenarios, you may wish to fetch only some of the fields from the entire document. For example, from the employees, we want to fetch all the employee’s names only or we want to fetch username and password, and so on.

Here Projection helps us in filtering the output data based on the input given. So, the basic rule for applying projection is to use 1 to include any record in out and 0 to exclude.

Command: db.collectionName.find({< filter fields leave it like {} if no filter >},{})

Example: db.employees.find({},{email:1})

>
db.employees.find({},{email:1})
{ "_id" : ObjectId("5f20577536c73fc3e870fda4"), "email" : "harvey.chambers@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fda5"), "email" : "victor.pedersen@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fda6"), "email" : "elijah.lewis@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fda7"), "email" : "olav.oehme@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fda8"), "email" : "carl.jacobs@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fda9"), "email" : "madeleine.till@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fdaa"), "email" : "shona.kemperman@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fdab"), "email" : "louise.graham@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fdac"), "email" : "zachary.lo@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fdad"), "email" : "isolino.viana@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fdae"), "email" : "katie.welch@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fdaf"), "email" : "sandra.lorenzo@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb0"), "email" : "mestan.kaplangı@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb2"), "email" : "gideon.vandrongelen@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb3"), "email" : "maeva.wilson@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb4"), "email" : "anaëlle.adam@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb5"), "email" : "anne.ruiz@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fdb6"), "email" : "delia.durand@example.com" }
Type "it" for more

I have explained above that use 1 to apply projection to fetch only that field or fields. But here we are getting _id as well. One thing to remember is that if you don’t want _id in the result you must explicitly mention it with 0 (zero) in projection like below.

Example: db.employees.find({},{email:1,_id:0})

> db.employees.find({},{email:1,_id:0})
{ "email" : "harvey.chambers@example.com" }
{ "email" : "victor.pedersen@example.com" }
{ "email" : "elijah.lewis@example.com" }
{ "email" : "olav.oehme@example.com" }
{ "email" : "carl.jacobs@example.com" }
{ "email" : "madeleine.till@example.com" }
{ "email" : "shona.kemperman@example.com" }
{ "email" : "louise.graham@example.com" }
{ "email" : "zachary.lo@example.com" }
{ "email" : "isolino.viana@example.com" }
{ "email" : "katie.welch@example.com" }
{ "email" : "sandra.lorenzo@example.com" }
{ "email" : "mestan.kaplangı@example.com" }
{ "email" : "gideon.vandrongelen@example.com" }
{ "email" : "maeva.wilson@example.com" }
{ "email" : "anaëlle.adam@example.com" }
{ "email" : "anne.ruiz@example.com" }
{ "email" : "delia.durand@example.com" }
Type "it" for more

Mongodb find count

The count() is used to fetch the count of documents inside a collection. If a filter is passed in find() it will return count documents matched with the input filter otherwise it will return the count of all the documents.

Command: db.collectionName.find({}).count()

Example: db.employees.find({}).count()

Mongodb findone latest

To get the latest record from the database we can use _id with find() method with the help of limit (1) like below.

Command: db.collectionName.find().sort({_id:-1}).limit(1)

Example: db.employees.find().sort({_id:-1}).limit(1)

But this can hit the performance if the underlying data is huge. In such a case we can use another approach like below.

Command: db.collectionName.find().limit(1).sort({$natural:-1})

here $natural:-1 means the order opposite of the one that records are inserted in.

Example: db.employees.find().limit(1).sort({$natural:-1})

Mongodb find like

Sometimes there can be a requirement to fetch the data from MongoDB using some keywords or with the data we don’t have completely. Something like the like operator in SQL. In such cases, we can use regex to fetch the data.

Command: db.collectionName.fin({property: // })

Example: db.employees.find({email:/vand/},{email:1})

> db.employees.find({email:/vand/},{email:1})
{ "_id" : ObjectId("5f20577536c73fc3e870fdb2"), "email" : "gideon.vandrongelen@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fede"), "email" : "melvyn.vanderent@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870fee3"), "email" : "querijn.vandenboorn@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870ff31"), "email" : "vanda.novaes@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e870ffb7"), "email" : "sanjeev.vanderborgh@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e8710265"), "email" : "nurullah.vanderkaaden@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e87102d8"), "email" : "pedram.vandenmunckhof@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e871032e"), "email" : "warner.vandenouweland@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e8710397"), "email" : "hulya.vandoremalen@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e87103f6"), "email" : "solomon.vanderheijde@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e8710495"), "email" : "dicky.vandermaat@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e871058b"), "email" : "jonno.vanderwal@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e8710699"), "email" : "tulay.vanderarend@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e871087d"), "email" : "mathys.vandelft@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e8710a5e"), "email" : "juul.vanderhaar@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e8710ab8"), "email" : "nur.vandiggelen@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e8710b56"), "email" : "patriek.vandepeppel@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e8710b87"), "email" : "remy.vandegeijn@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e8710bb0"), "email" : "karine.vandenbos@example.com" }
{ "_id" : ObjectId("5f20577536c73fc3e8710cba"), "email" : "halil.vanduinkerken@example.com" }
Type "it" for more

This is one of the ways of using regex. You can try other regex options as well.

Mongodb find in array

While querying the data and using a filter on an array if we use db.find({tags: ‘hello’}) – it will return all the collections having array tags and the array contains a hello. But if you want to fetch only those documents which only have tags hello then we have to pass it inside the square bracket like db.find({tags [‘hello’]}).

Similarly, we can use in and not in like below.

db.find({tags : {$in : [‘hello’,’goodbye’]}}) — to use in keyword
db.find({tags : {$nin : [‘hello’,’goodbye’]}}) — to use not in keyword

Example: 

>
 db.products.find()
{ "_id" : ObjectId("5f2149f5bff8019e3cd633ad"), "productName" : "Product 2", "price" : 199, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer", "winter" ] }
{ "_id" : ObjectId("5f2149f5bff8019e3cd633ae"), "productName" : "Product 3", "price" : 399, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer", "monsoon" ] }
{ "_id" : ObjectId("5f2149f5bff8019e3cd633af"), "productName" : "Product 4", "price" : 499, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer" ] }
{ "_id" : ObjectId("5f2149f5bff8019e3cd633b0"), "productName" : "Product 5", "price" : 599, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "winter" ] }


> db.products.find({usedIn: 'summer'})
{ "_id" : ObjectId("5f2149f5bff8019e3cd633ad"), "productName" : "Product 2", "price" : 199, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer", "winter" ] }
{ "_id" : ObjectId("5f2149f5bff8019e3cd633ae"), "productName" : "Product 3", "price" : 399, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer", "monsoon" ] }
{ "_id" : ObjectId("5f2149f5bff8019e3cd633af"), "productName" : "Product 4", "price" : 499, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer" ] }


> db.products.find({usedIn: ['summer']})
{ "_id" : ObjectId("5f2149f5bff8019e3cd633af"), "productName" : "Product 4", "price" : 499, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer" ] }

> db.products.find({usedIn: {$in: ['summer']}})
{ "_id" : ObjectId("5f2149f5bff8019e3cd633ad"), "productName" : "Product 2", "price" : 199, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer", "winter" ] }
{ "_id" : ObjectId("5f2149f5bff8019e3cd633ae"), "productName" : "Product 3", "price" : 399, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer", "monsoon" ] }
{ "_id" : ObjectId("5f2149f5bff8019e3cd633af"), "productName" : "Product 4", "price" : 499, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer" ] }


> db.products.find({usedIn: {$in: ['summer','mansoon']}})
{ "_id" : ObjectId("5f2149f5bff8019e3cd633ad"), "productName" : "Product 2", "price" : 199, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer", "winter" ] }
{ "_id" : ObjectId("5f2149f5bff8019e3cd633ae"), "productName" : "Product 3", "price" : 399, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer", "monsoon" ] }
{ "_id" : ObjectId("5f2149f5bff8019e3cd633af"), "productName" : "Product 4", "price" : 499, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer" ] }


> db.products.find({usedIn: {$in: ['winter','mansoon']}})
{ "_id" : ObjectId("5f2149f5bff8019e3cd633ad"), "productName" : "Product 2", "price" : 199, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer", "winter" ] }
{ "_id" : ObjectId("5f2149f5bff8019e3cd633b0"), "productName" : "Product 5", "price" : 599, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "winter" ] }


> db.products.find({usedIn: {$nin: ['winter','mansoon']}})
{ "_id" : ObjectId("5f2149f5bff8019e3cd633ae"), "productName" : "Product 3", "price" : 399, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer", "monsoon" ] }
{ "_id" : ObjectId("5f2149f5bff8019e3cd633af"), "productName" : "Product 4", "price" : 499, "receivedOn" : ISODate("2020-07-29T10:05:41.106Z"), "usedIn" : [ "summer" ] }

Mongodb cursor to toArray

The toArray() method iterates the cursor to exhaustion and returns a Promise that resolves to an array that contains all of the iterated documents.

Command: db.collectionName.find().toArray()

Example: db.employees.find().toArray()

That’s it in this post, here we discussed various ways to fetch the data from MongoDB, how to use projection, limiting the result, sorting the data, etc.

if you are starting with MongoDB. you can check my post on Setting up MongoDB and an introduction to shell

Reference https://docs.mongodb.com/realm/mongodb/

You can share other ways to achieve the above requirements or if you know better ways to do it.

Happy Learning !!