MongoDB vs PostgreSQL

July 21, 2018 | 7 Minute Read

MongoDB is classified as a NoSQL database program, it uses JSON-like documents with schemas. PostgreSQL is a relational database like MySQL.

SQL vs MongoDB Terminology and Concepts

SQL Terms/Concepts MongoDB Terms/Concepts
database database
table collection
row document or BSON document
column field
index index
table joins embedded documents and linking

primary key

Specify any unique column or column combination as primary key.

primary key

In MongoDB, the primary key is automatically set to the _id field.

aggregation (e.g. group by)

aggregation framework

See the SQL to Aggregation Framework Mapping Chart.

Examples

The following table presents the various SQL statements and the corresponding MongoDB statements. The examples in the table assume the following conditions:

  1. The SQL examples assume a table named users.
  2. The MongoDB examples assume a collection named users that contain documents of the following prototype:
{
  _id: ObjectID("509a8fb2f3f4948bd2f983a0"),
  user_id: "abc123",
  age: 55,
  status: 'A'
}

Create and Alter

SQL Schema Statements MongoDB Schema Statements
CREATE TABLE users (
        id MEDIUMINT NOT NULL
            AUTO_INCREMENT,
        user_id Varchar(30),
        age Number,
        status char(1),
        PRIMARY KEY (id)
     ) 

Implicitly created on first insert operation. The primary key _id is automatically added if _id field is not specified.

db.users.insert( {
        user_id: "abc123",
        age: 55,
        status: "A"
     } ) 

However, you can also explicitly create a collection:

db.createCollection("users") 
ALTER TABLE users
    ADD join_date DATETIME 
Collections do not describe or enforce the structure of the constituent documents. See the Schema Design wiki page for more information.
ALTER TABLE users
    DROP COLUMN join_date 
Collections do not describe or enforce the structure of the constituent documents. See the Schema Design wiki page for more information.
CREATE INDEX idx_user_id_asc
    ON users(user_id) 
db.users.ensureIndex( { user_id: 1 } ) 
CREATE INDEX
           idx_user_id_asc_age_desc
    ON users(user_id, age DESC) 
db.users.ensureIndex( { user_id: 1, age: -1 } ) 
DROP TABLE users 
db.users.drop() 

Select

SQL SELECT Statements MongoDB find() Statements
SELECT *
    FROM users 
db.users.find() 
SELECT id, user_id, status
    FROM users 
db.users.find(
            { },
            { user_id: 1, status: 1 }
        ) 
SELECT user_id, status
    FROM users
    
db.users.find(
        { },
        { user_id: 1, status: 1, _id: 0 }
    ) 
SELECT *
        FROM users
        WHERE status = "A"
        
db.users.find(
            { status: "A" }
        ) 
SELECT user_id, status
        FROM users
        WHERE status = "A"
        
db.users.find(
            { status: "A" },
            { user_id: 1, status: 1, _id: 0 }
        ) 
SELECT *
        FROM users
        WHERE status != "A"
        
db.users.find(
            { status: { $ne: "A" } }
        ) 
SELECT *
    FROM users
    WHERE status = "A"
    AND age = 50
    
db.users.find(
        { status: "A",
          age: 50 }
    )
    
SELECT *
    FROM users
    WHERE status = "A"
    OR age = 50
    
db.users.find(
        { $or: [ { status: "A" } ,
                 { age: 50 } ] }
    ) 
SELECT *
    FROM users
    WHERE age > 25
    
db.users.find(
        { age: { $gt: 25 } }
    ) 
SELECT *
    FROM users
    WHERE age < 25
    
db.users.find(
       { age: { $lt: 25 } }
    )
    
SELECT *
    FROM users
    WHERE age > 25
    AND   age <= 50
    
db.users.find(
       { age: { $gt: 25, $lte: 50 } }
    )
    
SELECT *
    FROM users
    WHERE user_id like "%bc%"
    
db.users.find(
       { user_id: /bc/ }
    )
    
SELECT *
    FROM users
    WHERE user_id like "bc%"
    
db.users.find(
       { user_id: /^bc/ }
    )
    
SELECT *
    FROM users
    WHERE status = "A"
    ORDER BY user_id ASC
    
db.users.find( { status: "A" } ).sort( { user_id: 1 } )
    
SELECT *
    FROM users
    WHERE status = "A"
    ORDER BY user_id DESC
    
db.users.find( { status: "A" } ).sort( { user_id: -1 } )
    
SELECT COUNT(*)
      FROM users 
db.users.count() 
db.users.find().count() 
SELECT COUNT(user_id)
    FROM users
    
db.users.count( { user_id: { $exists: true } } )
    
db.users.find( { user_id: { $exists: true } } ).count()
    
SELECT COUNT(*)
    FROM users
    WHERE age > 30 
db.users.count( { age: { $gt: 30 } } ) 
db.users.find( { age: { $gt: 30 } } ).count() 
SELECT DISTINCT(status)
    FROM users 
db.users.distinct( "status" )
    
SELECT *
        FROM users
        LIMIT 1 
db.users.findOne() 
db.users.find().limit(1)
        
SELECT *
        FROM users
        LIMIT 5
        SKIP 10 
db.users.find().limit(5).skip(10) 
EXPLAIN SELECT *
    FROM users
    WHERE status = "A" 
db.users.find( { status: "A" } ).explain() 

Update

SQL Update Statements MongoDB update() Statements
UPDATE users
    SET status = "C"
    WHERE age > 25
    
db.users.update(
       { age: { $gt: 25 } },
       { $set: { status: "C" } },
       { multi: true }
    )
    
UPDATE users
    SET age = age + 3
    WHERE status = "A"
    
db.users.update(
       { status: "A" } ,
       { $inc: { age: 3 } },
       { multi: true }
    )
    

Insert

SQL INSERT Statements MongoDB insert() Statements
INSERT INTO users(user_id, age, status)
    VALUES ("bcd001",
            45,
            "A")
    
db.users.insert( {
           user_id: "bcd001",
           age: 45,
           status: "A"
    } )
    

Delete

SQL Delete Statements MongoDB remove() Statements
DELETE FROM users
        WHERE status = "D" 
db.users.remove( { status: "D" } ) 
DELETE FROM users 
db.users.remove( ) 


The Path of a Query in PostgresSQL

Taken from the Postgres 10 documentation. Here we give a short overview of the stages a query has to pass in order to obtain a result.
  1. A connection from an application program to the PostgreSQL server has to be established. The application program transmits a query to the server and waits to receive the results sent back by the server.
  2. The parser stage checks the query transmitted by the application program for correct syntax and creates a query tree.
  3. The rewrite system takes the query tree created by the parser stage and looks for any rules (stored in the system catalogs) to apply to the query tree. It performs the transformations given in the rule bodies.
    One application of the rewrite system is in the realization of views. Whenever a query against a view (i.e., a virtual table) is made, the rewrite system rewrites the user's query to a query that accesses the base tables given in the view definition instead.
  4. The planner/optimizer takes the (rewritten) query tree and creates a query plan that will be the input to the executor.
    It does so by first creating all possible paths leading to the same result. For example if there is an index on a relation to be scanned, there are two paths for the scan. One possibility is a simple sequential scan and the other possibility is to use the index. Next the cost for the execution of each path is estimated and the cheapest path is chosen. The cheapest path is expanded into a complete plan that the executor can use.
  5. The executor recursively steps through the plan tree and retrieves rows in the way represented by the plan. The executor makes use of the storage system while scanning relations, performs sorts and joins, evaluates qualifications and finally hands back the rows derived.
Here is a illustrative examplanation of the PostgreSQL query lifecycle: http://patshaughnessy.net/2014/10/13/following-a-select-statement-through-postgres-internals


References—
a

  1. https://gist.github.com/aponxi/4380516
  2. Postgresql 10 documentation
  3. PostgreSQL query life cycle