Thursday, March 21, 2024

Differences between SQL and NoSQL

The table below summarizes the main differences between SQL and NoSQL databases.

SQL DatabasesNoSQL Databases
Data Storage ModelTables with fixed rows and columnsDocument: JSON documents, Key-value: key-value pairs, Wide-column: tables with rows and dynamic columns, Graph: nodes and edges
Development HistoryDeveloped in the 1970s with a focus on reducing data duplicationDeveloped in the late 2000s with a focus on scaling and allowing for rapid application change driven by agile and DevOps practices.
ExamplesOracle, MySQL, Microsoft SQL Server, and PostgreSQLDocument: MongoDB and CouchDB, Key-value: Redis and DynamoDB, Wide-column: Cassandra and HBase, Graph: Neo4j and Amazon Neptune
Primary PurposeGeneral purposeDocument: general purpose, Key-value: large amounts of data with simple lookup queries, Wide-column: large amounts of data with predictable query patterns, Graph: analyzing and traversing relationships between connected data
SchemasRigidFlexible
ScalingVertical (scale-up with a larger server)Horizontal (scale-out across commodity servers)
Multi-Record ACID TransactionsSupportedMost do not support multi-record ACID transactions. However, some — like MongoDB — do.
JoinsTypically requiredTypically not required
Data to Object MappingRequires ORM (object-relational mapping)Many do not require ORMs. MongoDB documents map directly to data structures in most popular programming languages.

What type of information is stored in a database?

Databases are used in most modern applications, whether the database is on your personal phone, computer, or the internet. An operational database system will store much of the data an application needs to function, keeping the data organized and allowing users to access the data.

If you were building an eCommerce app, some of the data you might access and store in your operational database system includes:

Customer data 

-like usernames, email addresses, and preferences.

Business data

- like product colors, prices, and ratings.

Relationship data

- like the locations of stores with a specific product in stock.

Wednesday, March 20, 2024

How Many Types of Databases Are There?

There are nearly a dozen types of database. Some of the more commonly used categories of database include:

Hierarchical Databases

Developed in the 1960s, the hierarchical database looks similar to a family tree. A single object (the “parent”) has one or more objects beneath it (the “child”). No child can have more than one parent. In exchange for the rigid and complex navigation of the parent child structure, the hierarchical database offers high performance, as there’s easy access and a quick querying time. The Windows Registry is one example of this system.

Relational Databases

Relational databases are a system designed in the 1970s. This database commonly uses Structured Query Language (SQL) for operations like creating, reading, updating, and deleting (CRUD) data.

This database stores data in discrete tables, which can be joined together by fields known as foreign keys. For example, you might have a User table that contains data about your users, and join the users table to a Purchases table, which contains data about the purchases the users have made. MySQL, Microsoft SQL Server, and Oracle are examples.

Non-Relational Databases

Non-relational management systems are commonly referred to as NoSQL databases. This type of database matured due to increasingly complex modern web applications. These databases' varieties have proliferated over the last decade. Examples include MongoDB and Redis.

Object oriented databases

Object oriented databases store and manage objects on a database server's disk. Object oriented databases are unique because associations between objects can persist. This means that object oriented programming and the querying of data across complex relationships is fast and powerful. One example of an object oriented database is MongoDB Realm, where the query language constructs native objects through your chosen SDK. Object oriented programming is the most popular programming paradigm. 

NoSQL

NoSQL is an umbrella term for any alternative system to traditional SQL databases. Sometimes, when we say NoSQL management systems, we mean any database that doesn't use a relational model. NoSQL databases use a data model that has a different structure than the rows and columns table structure used with RDBMS.

NoSQL databases are different from each other. There are four kinds of this database: 

document databases, 
key-value stores, 
column-oriented databases, and
Graph databases


Document databases

A document database stores data in JSON, BSON, or XML documents. Documents in the database can be nested. Particular elements can be indexed for faster querying.

You can access, store, and retrieve documents from your network in a form that is much closer to the data objects used in applications, which means less translation is required to use and access the data in an application. SQL data must often be assembled and disassembled when moving between applications, storage, or more than one network.

Document databases are popular with developers because they offer the flexibility to rework their document structures as needed to suit their applications. The flexibility of this database speeds development — data becomes like code and is under the control of developers. They can more easily access and use it. In SQL databases, intervention by database administrators may be required to change the structure of a database.

Document databases are usually implemented with a scale-out architecture, providing a path to the scalability of data volumes and traffic. Use cases include eCommerce platforms, trading platforms, and mobile app development.

Key-value stores

This is the simplest type of NoSQL database. Every element is stored as a key-value pair consisting of an attribute name ("key") and a value. This database is like an RDBMS with two columns: the attribute name (such as "state") and the value (such as "Alaska").

Use cases for NoSQL databases include shopping carts, user preferences, and user profiles.

Column-oriented databases

While an RDBMS stores data in rows and reads it row by row, column-oriented databases are organized as a set of columns. When you want to run analytics on a small number of columns in the network, you can read those columns directly without consuming memory with unwanted data. Columns are of the same type and benefit from more efficient compression, making reads even faster. A column-oriented database can aggregate the value of a given column (adding up sales for the year, for example). Use cases of a column-oriented database include analytics.

While column-oriented databases are great for analytics, the way they write data makes it difficult for them to be consistent as writes of all the columns in the column-oriented database require multiple write events on disk. Relational databases don't suffer from this problem as row data is written contiguously to disk.

Graph databases

A graph database focuses on the relationship between data elements. Each element is contained as a node. The connections between elements in the database are called links or relationships. Connections are first-class elements of the database, stored directly.

A graph database is optimized to capture and search the connections between elements, overcoming the overhead associated with JOINing several tables in SQL. Very few real-world business systems can survive solely on graph databases. As a result, graph databases are usually run alongside more traditional databases.

Use cases include fraud detection and social networks.

These databases are diverse in their data formats and applications. Furthermore, systems store data in different ways:

Data can be stored in a structured document, similar to JSON (JavaScript Object Notation). MongoDB is a popular document distributed database.

Data can be in a key-value format that maps a single attribute (key) to its value. Redis and Riak KV are examples. They’re typically used for simple one-to-one relationships, like associating users with preferences.

A graph datastore uses nodes to represent objects and edges to describe the relationship between them. Neo4j is one example.

These differ from RDBMS in that they can be schema-agnostic, allowing unstructured and semi-structured data in a network to be stored and processed.

Database

 A database(DB) is a collection of data in a format that can be easily accessed (Digital). A software application used to manage our DB is called DBMS (Database Management System).

Or

A database is an organized collection of data stored in a computer system and usually controlled by a database management system (DBMS).

Tuesday, May 4, 2010

Visitor Pattern

The visitor pattern is a behavioral object design pattern. The visitor pattern is used to simplify operations on groupings of related objects. These operations are performed by the visitor rather than by placing this code in the classes being visited. Since the operations are performed by the visitor rather than by the classes being visited, the operation code gets centralized in the visitor rather than being spread out across the grouping of objects, thus leading to code maintainability. The visitor pattern also avoids the use of the instanceof operator in order to perform calculations on similar classes.
In the visitor pattern, we have a Visitor interface that declares visit() methods for the various types of elements that can be visited. Concrete Visitors implement the Visitor interface's visit() methods. The visit() methods are the operations that should be performed by the visitor on an element being visited.
The related classes that will be visited implement an Element interface that declares an accept() method that takes a visitor as an argument. Concrete Elements implement the Element interface and implement the accept() method. In the accept() method, the visitor's visit() method is called with 'this', the current object of the Concrete Element type.
The elements to visit all implement the accept() method that takes a visitor as an argument. In this method, they call the visitor's visit() method with 'this'. As a result of this, an element takes a visitor and then the visitor performs its operation on the element.
Let's illustrate the visitor pattern with an example. First, we'll define a NumberVisitor interface. This interface declares three visit methods which take different types as arguments. Note that if we only wrote one visit method, we'd have to use the instanceof operator or a similar technique to handle the different element types. However, since we have separate visit methods, we don't need the instanceof operator, since each visit method handles a different type.

NumberVisitor.java

package com.cakes;

import java.util.List;

public interface NumberVisitor {

 public void visit(TwoElement twoElement);

 public void visit(ThreeElement threeElement);

 public void visit(List elementList);

}
All of the elements classes to be visited will implement the NumberElement interface. This interface has a single method that takes a NumberVisitor as an argument.

NumberElement.java

package com.cakes;

public interface NumberElement {

 public void accept(NumberVisitor visitor);

}
Let's create a TwoElement class that implements NumberElement. It has two int fields. Its accept() method calls the visitor's visit() method with 'this'. The operator to be performed on TwoElement is performed by the visitor.

TwoElement.java

package com.cakes;

public class TwoElement implements NumberElement {

 int a;
 int b;

 public TwoElement(int a, int b) {
  this.a = a;
  this.b = b;
 }

 @Override
 public void accept(NumberVisitor visitor) {
  visitor.visit(this);
 }

}
The ThreeElement class is similar to TwoElement, except that it has three int fields.

ThreeElement.java

package com.cakes;

public class ThreeElement implements NumberElement {

 int a;
 int b;
 int c;

 public ThreeElement(int a, int b, int c) {
  this.a = a;
  this.b = b;
  this.c = c;
 }

 @Override
 public void accept(NumberVisitor visitor) {
  visitor.visit(this);
 }

}
Now, let's create a visitor called SumVisitor that implements the NumberVisitor interface. For TwoElement and ThreeElement objects, this visitor will sum up the int fields. For a List of NumElements (ie, TwoElement and ThreeElement objects), this visitor will iterate over the elements and call their accept() methods. As a result of this, the visitor will perform visit operations on all the TwoElement and ThreeElement objects that make up the list, since the call to accept() in turn calls the visitor's visit methods for the TwoElement and ThreeElement objects. 

SumVisitor.java

package com.cakes; import java.util.List; public class SumVisitor implements NumberVisitor { @Override public void visit(TwoElement twoElement) { int sum = twoElement.a + twoElement.b; System.out.println(twoElement.a + "+" + twoElement.b + "=" + sum); } @Override public void visit(ThreeElement threeElement) { int sum = threeElement.a + threeElement.b + threeElement.c; System.out.println(threeElement.a + "+" + threeElement.b + "+" + threeElement.c + "=" + sum); } @Override public void visit(List elementList) { for (NumberElement ne : elementList) { ne.accept(this); } } } Here is another visitor, TotalSumVisitor. In addition to summing up the int fields and displaying the sum, this visitor will keep track of the total sums of all the elements that are visited.

TotalSumVisitor.java

package com.cakes; import java.util.List; public class TotalSumVisitor implements NumberVisitor { int totalSum = 0; @Override public void visit(TwoElement twoElement) { int sum = twoElement.a + twoElement.b; System.out.println("Adding " + twoElement.a + "+" + twoElement.b + "=" + sum + " to total"); totalSum += sum; } @Override public void visit(ThreeElement threeElement) { int sum = threeElement.a + threeElement.b + threeElement.c; System.out.println("Adding " + threeElement.a + "+" + threeElement.b + "+" + threeElement.c + "=" + sum + " to total"); totalSum += sum; } @Override public void visit(List elementList) { for (NumberElement ne : elementList) { ne.accept(this); } } public int getTotalSum() { return totalSum; } } Let's see the visitor pattern in action. The Demo class creates two TwoElement objects and one ThreeElement object. It creates a list of NumberElements and adds the TwoElement object and the ThreeElement object to the list. Next, we create a SumVisitor and we visit the list with the SumVisitor. After this, we create a TotalSumVisitor and visit the list with the TotalSumVisitor. We display the total sum via the call to TotalSumVisitor's getTotalSum() method.

Demo.java

package com.cakes; import java.util.ArrayList; import java.util.List; public class Demo { public static void main(String[] args) { TwoElement two1 = new TwoElement(3, 3); TwoElement two2 = new TwoElement(2, 7); ThreeElement three1 = new ThreeElement(3, 4, 5); List numberElements = new ArrayList(); numberElements.add(two1); numberElements.add(two2); numberElements.add(three1); System.out.println("Visiting element list with SumVisitor"); NumberVisitor sumVisitor = new SumVisitor(); sumVisitor.visit(numberElements); System.out.println("\nVisiting element list with TotalSumVisitor"); TotalSumVisitor totalSumVisitor = new TotalSumVisitor(); totalSumVisitor.visit(numberElements); System.out.println("Total sum:" + totalSumVisitor.getTotalSum()); } } The console output of executing Demo is shown here.

Console Output

Visiting element list with SumVisitor 3+3=6 2+7=9 3+4+5=12 Visiting element list with TotalSumVisitor Adding 3+3=6 to total Adding 2+7=9 to total Adding 3+4+5=12 to total Total sum:27 Notice that if we'd like to perform new operations on the grouping of elements, all we would need to do is write a new visitor class. We would not have to make any additions to the existing element classes, since they provide the data but none of the code for the operations.

Template Method Pattern

The template method pattern is a behavioral class pattern. A behavioral class pattern uses inheritance for distribution of behavior. In the template method pattern, a method (the 'template method') defines the steps of an algorithm. The implementation of these steps (ie, methods) can be deferred to subclasses. Thus, a particular algorithm is defined in the template method, but the exact steps of this algorithm can be defined in subclasses. The template method is implemented in an abstract class. The steps (methods) of the algorithm are declared in the abstract class, and the methods whose implementations are to be delegated to subclasses are declared abstract.
Here is an example of the template method pattern. Meal is an abstract class with a template method called doMeal() that defines the steps involved in a meal. We declare the method as final so that it can't be overridden. The algorithm defined by doMeal() consists of four steps: prepareIngredients(), cook(), eat(), and cleanUp(). The eat() method is implemented although subclasses can override the implementation. The prepareIngredients(), cook(), and cleanUp() methods are are declared abstract so that subclasses need to implement them.

Meal.java

package com.cakes;

public abstract class Meal {

 // template method
 public final void doMeal() {
  prepareIngredients();
  cook();
  eat();
  cleanUp();
 }

 public abstract void prepareIngredients();

 public abstract void cook();

 public void eat() {
  System.out.println("Mmm, that's good");
 }

 public abstract void cleanUp();

}
The HamburgerMeal class extends Meal and implements Meal's three abstract methods.

HamburgerMeal.java

package com.cakes;

public class HamburgerMeal extends Meal {

 @Override
 public void prepareIngredients() {
  System.out.println("Getting burgers, buns, and french fries");
 }

 @Override
 public void cook() {
  System.out.println("Cooking burgers on grill and fries in oven");
 }

 @Override
 public void cleanUp() {
  System.out.println("Throwing away paper plates");
 }

}
The TacoMeal class implements Meal's three abstract methods and also overrides the eat() method.

TacoMeal.java

package com.cakes;

public class TacoMeal extends Meal {

 @Override
 public void prepareIngredients() {
  System.out.println("Getting ground beef and shells");
 }

 @Override
 public void cook() {
  System.out.println("Cooking ground beef in pan");
 }

 @Override
 public void eat() {
  System.out.println("The tacos are tasty");
 }

 @Override
 public void cleanUp() {
  System.out.println("Doing the dishes");
 }

}
The Demo class creates a HamburgerMeal object and calls its doMeal() method. It creates a TacoMeal object and calls doMeal() on the TacoMeal object.

Demo.java

package com.cakes;

public class Demo {

 public static void main(String[] args) {

  Meal meal1 = new HamburgerMeal();
  meal1.doMeal();

  System.out.println();

  Meal meal2 = new TacoMeal();
  meal2.doMeal();

 }

}
The console output of the execution of Demo is shown here.

Console Output

Getting burgers, buns, and french fries
Cooking burgers on grill and fries in oven
Mmm, that's good
Throwing away paper plates

Getting ground beef and shells
Cooking ground beef in pan
The tacos are tasty
Doing the dishes
As you can see, the template method design pattern allows us to define the steps in an algorithm and pass the implementation of these steps to subclasses.

Startergy Pattern

The strategy pattern is a behavioral object design pattern. In the strategy pattern, different algorithms are represented as Concrete Strategy classes, and they share a common Strategy interface. A Context object contains a reference to a Strategy. By changing the Context's Strategy, different behaviors can be obtained. Although these behaviors are different, the different strategies all operate on data from the Context.
The strategy pattern is one way that composition can be used as an alternative to subclassing. Rather than providing different behaviors via subclasses overriding methods in superclasses, the strategy pattern allows different behaviors to be placed in Concrete Strategy classes which share the common Strategy interface. A Context class is composed of a reference to a Strategy.
Here is an example of the strategy pattern. First, we'll define a Strategy interface. It declares a checkTemperature() method.

Strategy.java

package com.cakes;

public interface Strategy {

 boolean checkTemperature(int temperatureInF);

}
The HikeStrategy class is a concrete strategy class that implements the Strategy interface. The checkTemperature method is implemented so that if the temperature is between 50 and 90, it returns true. Otherwise it returns false.

HikeStrategy.java

package com.cakes;

public class HikeStrategy implements Strategy {

 @Override
 public boolean checkTemperature(int temperatureInF) {
  if ((temperatureInF >= 50) && (temperatureInF <= 90)) {
   return true;
  } else {
   return false;
  }
 }

}
The SkiStrategy implements the Strategy interface. If the temperature is 32 or less, the checkTemperature method returns true. Otherwise it returns false.

SkiStrategy.java

package com.cakes;

public class SkiStrategy implements Strategy {

 @Override
 public boolean checkTemperature(int temperatureInF) {
  if (temperatureInF <= 32) {
   return true;
  } else {
   return false;
  }
 }

}
The Context class contains a temperature and a reference to a Strategy. The Strategy can be changed, resulting in different behavior that operates on the same data in the Context. The result of this can be obtained from the Context via the getResult() method.

Context.java

package com.cakes;

public class Context {

 int temperatureInF;
 Strategy strategy;

 public Context(int temperatureInF, Strategy strategy) {
  this.temperatureInF = temperatureInF;
  this.strategy = strategy;
 }

 public void setStrategy(Strategy strategy) {
  this.strategy = strategy;
 }

 public int getTemperatureInF() {
  return temperatureInF;
 }

 public boolean getResult() {
  return strategy.checkTemperature(temperatureInF);
 }

}
The Demo class creates a Context object with a temperature of 60 and with a SkiStrategy. It displays the temperature from the context and whether that temperature is OK for skiing. After that, it sets the Strategy in the Context to HikeStrategy. It then displays the temperature from the context and whether that temperature is OK for hiking. 

Demo.java

package com.cakes; public class Demo { public static void main(String[] args) { int temperatureInF = 60; Strategy skiStrategy = new SkiStrategy(); Context context = new Context(temperatureInF, skiStrategy); System.out.println("Is the temperature (" + context.getTemperatureInF() + "F) good for skiing? " + context.getResult()); Strategy hikeStrategy = new HikeStrategy(); context.setStrategy(hikeStrategy); System.out.println("Is the temperature (" + context.getTemperatureInF() + "F) good for hiking? " + context.getResult()); } } The console output of executing Demo is shown here.

Console Output

Is the temperature (60F) good for skiing? false Is the temperature (60F) good for hiking? true