How to Create and Use Indexes in MongoDB Database

MongoDB supports creation of indexes to speed up queries for specific application needs. With suitable indexes, MongoDB doesn't need to scan every document before returning results. This substantially speeds up queries especially for large collections where ordering and filtering is needed. MongoDB automatically creates a uniq index on the _id field during the creation of the collection. All other indexes must be manually created.

MongoDB indexes are created on a single field or a combination of fields and you can specify ascending or descending order for the index. In the following example I will use a typical use of a collection which is used to store customer data of a CRM system. First let us see how adding a simple index on a single collection field can substantially improve query performance.

Creating and Using Single Field Indexes in MongoDB

Our application uses a collection named customer to store customer data. Let us first create the collection using MongoDB JavaScript commands,

// create a customer collection
db.createCollection("customer");

Let us now insert some test data into the collection. The following script uses a loop to create 100,000 customer records in the collection. Each record contains customer name and age. We simulate different ages using modulus operator on the loop index. This ensures that customer ages are between 10 and 100.

// Create a large customer data set!
for(i=1;i<=100000;i++) {
    db.customer.insert({ name:"jack"+i, age:i%90+10 });
};

Let us now run a query to get the list of customers in the ascending order of their age,

// display all customers in ascending order of age. 
db.customer.find().sort( { age: 1 } )

In my machine, the above query took about 0.22 seconds. For a single query this may not seem much, but when multiple queries are run by different users, this becomes a major bottleneck on the database.

Let us now create an ascending index on the age column which we are using in the above sort query.

// We create an index on age to speed up sorted query on age
db.customer.createIndex( { age: 1 } )

Now let us now run the sort query again.

// display all customers in ascending order of age. This uses our index.
db.customer.find().sort( { age: 1 } )

This time the query took about 0.002 seconds to run. The query is now more than 100 times faster! Hence it is very important that you have proper indexes on your MongoDB tables especially when you are building a system for large number of application users with fairly large data. The advantage is substantially high when you have large documents in the collection.

Note that in the above example the order of the index doesn't matter. This is because for single field indexes like the one above on age, MongoDB can traverse the index in either direction. However order of index does matter in the case of compound indexes containing multiple fields.

Creating and Using Multi-Field Indexes in MongoDB

Let us know explore a much complex scenario involving compound indexes and multiple sort columns. We will start with an application scenario and see how multiple compound indexes can improve queries substantially.

In our e-commerce application, we have a collection for storing all the retail stores of the company. For simplicity, assume that the collection contains store name, store country and store city. If you consider this as a global retailer, there will be thousands of stores in the collection. Let us create the collection and then add 50,000 stores with random data,

// create a store collection
db.createCollection("store");
// Create a large store data set! 
//For the test data, we randomly create 2 letter strings 
//for country names and randomly create 8 letter strings 
//for city names.
for(i=1;i<=50000;i++) {
    var charset = "abcdefghijklmnopqrstuvwxyz";
    var city = ""; var country="";
    for( var j=0; j < 2; j++ )
        country += charset[Math.floor(Math.random() * charset.length)];
    for( var j=0; j < 8; j++ )
        city += charset[Math.floor(Math.random() * charset.length)];
    db.store.insert({ name:"store"+i, country:country, city: city });
};

In our e-commerce application, we are displaying the list of stores which is sorted first with country name and then with city name in ascending alphabetical order. The query is given below,

db.store.find().sort( { country: 1, city:1 } )

This query takes about 0.18 seconds in my machine. To improve the query performance, I added the following compound index which contains both country and city. I also indicate that the sort order for index is ascending for both fields.

db.store.createIndex( { country: 1, city:1 } )

With this index in place, my original query is run again,

db.store.find().sort( { country: 1, city:1 } )

This time the query taken less than 0.003 seconds! A huge improvement. Now application requires the store listing to be first sorted on the descending order of country followed by descending order of city name. The new query is given below,

db.store.find().sort( { country: -1, city:-1 } )

This time also the query taken less than 0.003 seconds! This means our index is also working even when reverse sort oder for both fields.

Now let us try running the query with ascending order of country followed by descending order of city name.

db.store.find().sort( { country: 1, city:-1 } )

This time query performance is back to non indexed behavior. Our compound index is no longer working for this scenario. We need to create another compound index given below,

db.store.createIndex( { country: 1, city:-1 } )

With this index also in place, now the queries are faster even with all 4 combinations of the sort order for country name and city name.

Now let us see what happens if you use only one of the fields of compound index in your sort order.

db.store.find().sort( { country: 1 } )

It is fast! This query also uses compound index even when the sort query uses only country field. This is because in MongoDB, compound indexes work even when only index prefixes(one or more first parts of a compound index) are used in the sort query.

However, the following queries are still slower since you are running the sort query on the second city name field (NOT an index prefix).

db.store.find().sort( { city: 1 } )
db.store.find().sort( { city: -1 } )

For the above query to work faster, you need to add the following index,

db.store.createIndex( { city:1 } )

So if we need all sort order combinations in our application, we will need the following indexes,

db.store.createIndex( { city:1 } )
db.store.createIndex( { country: 1, city:-1 } )
db.store.createIndex( { country: 1, city:1 } )

MongoDB supports following types of indexes - single field, compound index, multi-key index, geospatial index, text index and hashed index. Indexes can have different properties as well. See this page for more details. Also note that any kind of index increases storage needs of your MongoDB instance.

Please note that all the examples given above are tested on MongoDB 3.6. These scripts should also work if you are using MongoDB 3.6 API on a CosmosDB database. In the earlier version of CosmosDB (using MongoDB API 3.2), all top level fields were auto indexed. But this is no longer the case in newer CosmosDB versions. Hence it is important to identify and create indexes as needed in your application features.

How to Draw a Chessboard in HTML Canvas Using JavaScript

The canvas HTML element provides a bitmap area for graphics drawing. The canvas was standardized across various browsers in the HTML5 specification. Using JavaScript, we can draw 2D/3D images and animation on a canvas. Almost all modern browsers support canvas. With a hardware accelerated browser, Canvas can produce fast 2D graphics.

The following tutorial is intended as an introduction to Canvas 2D drawing using JavaScript. We will draw a chess board using some of the basic drawing primitives available on the canvas element. See the Mozilla canvas tutorial for a detailed look at the canvas API.

Let us create a simple HTML file(index.html) which contains the canvas element. Using the script tag, we will import the the JavaScript file(chess.js) containing the drawing commands for chessboard. When the HTML file is opened in a browser, the onload event on the body tag is triggered. This in turn calls the JavaScript method drawChessboard() defined in the script tag of the HTML page. The full source code of the index.html is given below.

<html>
  <head>
    <meta charset="UTF-8">
    <title>Draw Chess Board</title>
    <script src="chess.js"></script>
  </head>
  <body onload="drawChessboard()">
    <canvas id="canvasChessboard" width="800px" height="500px"></canvas>
  </body>
</html>

Let us now create chess.js which contains the JavaScript code for drawing the chessboard. Ensure that you have chess.js and index.html in the same folder. The full source code of chess.js is given below,

function drawChessboard() {
  // size of each chess square
  const squareSize = 50;
  // position of board's top left
  const boardTopx = 50;
  const boardTopy = 50;
  let canvas = document.getElementById("canvasChessboard");
  context = canvas.getContext("2d");
  for(let i=0; i<8; i++) {
    for(let j=0; j<8; j++) {
      context.fillStyle = ((i+j)%2==0) ? "white":"black";
      let xOffset = boardTopx + j*squareSize;
      let yOffset = boardTopy + i*squareSize;
      context.fillRect(xOffset, yOffset, squareSize, squareSize);
    }
  }
  // draw the border around the chessboard
  context.strokeStyle = "black";
  context.strokeRect(boardTopx, boardTopy, squareSize*8, squareSize*8)
}

The drawChessboard() method gets a reference to the canvas element using the getElementById() method. We then create a 2d drawing context using the getContext() method of canvas object. Finally a nested loop draws all the 64 squares of the chess board. The squares are drawn using white or black color depending on the position of the square in the board.

The final output of the chessboard drawing JavaScript code is given below,
chessboard in javascript

How to Draw Rectangles and Squares Using Python Turtle

Python's turtle package can be used to draw various shapes on a canvas. Turtle allows the programmer to move a pen in a specified direction by specifying its heading and distance. Turtle has no built-in primitive for drawing a rectangle or square. However it is easy to create a function to draw a rectangle(or square) in turtle.

The following python program defines a custom function for drawing rectangles using turtle. Note that the centre of the turtle canvas is at 0,0. Hence if you draw just a dot at (0,0) it will be at the centre of the drawing canvas. The function draw_rectangle() requires the co-ordinates of the top left of the rectangle. You also need to specify width, height, thickness and color of the rectangle.

The following example draws a blue rectangle which is 200 pixels in width and 100 pixels in height. We have specified the top left of the rectangle as (-100,50) to position the rectangle at the centre of the canvas. The rectangle drawn has a thickness of 5 pixels.

import turtle
turtle.setup(500,500)
board = turtle.Turtle()

# draws a rectangle given top left position of a rectangle
def draw_rectangle(board,x,y,width,height,size,color):
  board.pencolor(color)
  board.pensize(size)
  board.setheading(0)

  board.up()
  board.goto(x,y)
  board.down()
  # draw top
  board.forward(width)
  # draw right
  board.right(90)
  board.forward(height)
  # draw bottom
  board.right(90)
  board.forward(width)
  # draw left
  board.right(90)
  board.forward(height)
  board.end_fill()


# in turtle, the centre of the canvas is 0,0
# hence we position the rectangle in the center
# note that we need to pass the top left co-ordinates of rectangle
# draws rectangle with 200 pixels in width and 100 pixels in height
draw_rectangle(board,-100,50,200,100,5,"blue")
turtle.done()

The following the sample output from the program,

Following python program is a different version which also allows us to specify a fill color for the rectangle. The example is identical to the previous one except that we use a different color to fill the rectangle.

import turtle
turtle.setup(500,500)
board = turtle.Turtle()

# draws a rectangle given top left position of a rectangle
def draw_filled_rectangle(board,x,y,width,height,size,color,fill):
  board.fillcolor(fill)
  board.pencolor(color)
  board.pensize(size)
  board.setheading(0)

  board.begin_fill()
  board.up()
  board.goto(x,y)
  board.down()
  # draw top
  board.forward(width)
  # draw right
  board.right(90)
  board.forward(height)
  # draw bottom
  board.right(90)
  board.forward(width)
  # draw left
  board.right(90)
  board.forward(height)
  board.end_fill()


# in turtle, the centre of the canvas is 0,0
# hence we position the rectangle in the center
# note that we need to pass the top left co-ordinates of rectangle
# draws rectangle with 200 pixels in width and 100 pixels in height
# also specifies the rectangle color and the fill color
draw_filled_rectangle(board,-100,50,200,100,5,"blue","green")
turtle.done()

The following the sample output from the program showing a filled rectangle,

The following program uses looping to draw a two dimensional matrix of identical black squares. Note that we are using black as fill color and white as the stroke color for the rectangles.

import turtle
turtle.setup(500,500)
board = turtle.Turtle()

# draws a rectangle given top left position of a rectangle
def draw_filled_rectangle(board,x,y,width,height,size,color,fill):
  board.fillcolor(fill)
  board.pencolor(color)
  board.pensize(size)
  board.setheading(0)

  board.begin_fill()
  board.up()
  board.goto(x,y)
  board.down()
  # draw top
  board.forward(width)
  # draw right
  board.right(90)
  board.forward(height)
  # draw bottom
  board.right(90)
  board.forward(width)
  # draw left
  board.right(90)
  board.forward(height)
  board.end_fill()

# draw a 7x7 matrix of black squares
for x in range(1,8):
  for y in range(1,8):
    draw_filled_rectangle(board,-200+x*20,y*20,20,20,2,"white","black")

turtle.done()

The following the sample output of 7x7 matrix of black squares from the python turtle program,

How to Draw Circles Using Python Turtle

Python contains an interesting drawing module called Turtle. This module is available as part of the standard python distribution. Turtle consists of a number of graphics operations modelled after pen drawing. In this article I will show you how we can use the turtle commands to draw circle based shapes.

How to Draw a Simple Circle Using Python Turtle

The following python script creates a simple circle with default color at the center of the turtle canvas. We have defined the turtle canvas with a width of 800 pixels and a height of 600 pixels. We then draw a circle of radius 100 pixels in the middle of the canvas. Note that the bottom of the circle is placed in the middle of the canvas.

import turtle

turtle.setup(800,600)
board = turtle.Turtle()

board.penup()
board.setpos(0,0)
board.pendown()
board.circle(100)

turtle.done()

How to Draw a Face Using Python Turtle

The following python script draws the shape of a face using the turtle commands. We have organized the code in functions so that each section of the drawing is separate. Note that we are resetting the direction of the pen after drawing part of a circle in the draw_lip functions.

import turtle
turtle.setup(800,600)
board = turtle.Turtle()

def draw_face():
  board.penup()
  board.setpos(0,0)
  board.pendown()
  board.circle(100)

def draw_left_eye():
  board.penup()
  board.setpos(-50,100)
  board.pendown()
  board.circle(25)

def draw_right_eye():
  board.penup()
  board.setpos(50,100)
  board.pendown()
  board.circle(25)

def draw_right_lip():
  board.penup()
  board.setpos(0,25)
  board.pendown()
  board.circle(100,45)
  board.setheading(0)

def draw_left_lip():
  board.penup()
  board.setpos(0,25)
  board.pendown()
  board.circle(100,-45)
  board.setheading(0)

draw_face()
draw_left_eye()
draw_right_eye()
draw_left_lip()
draw_right_lip()

board.penup()
board.setpos(400,400)
turtle.done()

How to Draw Tangent Circles Using Python Turtle

The following python program creates tangent circles at the middle of the canvas. We use a loop to generate the circles and for each iteration we just change the radius of the circle.

import turtle
turtle.setup(800,600)
board = turtle.Turtle()

for i in range(1,20):
  board.circle(i*10)

turtle.done()

How to Draw Concentric Circles Using Python Turtle

The following python program creates concentric circles at the middle of the canvas. We use a loop to generate the circles and for each iteration we change the y location and the radius of the circle.

import turtle
turtle.setup(800,600)
board = turtle.Turtle()

for i in range(1,20):
  board.circle(i*10)
  board.penup()
  board.sety(-i*10)
  board.pendown()

turtle.done()

How to Draw Olympics Logo Using Python Turtle

The following python program creates the olympics logo using the the turtle package. It also demonstrates the use of pen color and pen size in drawing shapes.

import turtle
turtle.setup(800,600)
board = turtle.Turtle()


circle_positions = [(-120,0,"blue"), (0,0,"black"), (120,0,"red"),
                    (-60,-60,"yellow"), (60,-60,"green")]

for pos in circle_positions:
  board.penup()
  board.setpos(pos[0],pos[1])
  board.pencolor(pos[2])
  board.pensize(5)
  board.pendown()
  board.circle(50)

turtle.done()

How to Create Canvas Animation Using Tkinter

Tkinter is one of the most popular GUI toolkits available for python. It is available as part of the standard python installation. Hence you can use this package without installing any additional modules. Tkinter is a powerful GUI library and you can use it to build full fledged user interfaces or build simple desktop games.

This article contains a step by step guide on building an animation using the python tkinter package. We will be using canvas object of the tkinter package to draw our animation. Note that the following program requires python 3.6 or above.

The following python program creates a simple animation showing the movement of a ball across the screen. Following are the steps in the program,

  • Create and display main window of the application
  • Create and attach the canvas to the main window. We will be drawing to this canvas
  • Draw and animate a circle (our ball) inside the canvas

Let us start by importing tkinter and time modules. We will use time module to introduce a delay for drawing successive screens of the animation,

import tkinter
import time

Let us now create a set of variables for our animation demo. This defines the size of our gaming canvas, speed of the ball, size of the ball and where we want our ball to start moving from.

# width of the animation window
animation_window_width=800
# height of the animation window
animation_window_height=600
# initial x position of the ball
animation_ball_start_xpos = 50
# initial y position of the ball
animation_ball_start_ypos = 50
# radius of the ball
animation_ball_radius = 30
# the pixel movement of ball for each iteration
animation_ball_min_movement = 5
# delay between successive frames in seconds
animation_refresh_seconds = 0.01

The following function creates the application window with the specified title and dimensions,

# The main window of the animation
def create_animation_window():
  window = tkinter.Tk()
  window.title("Tkinter Animation Demo")
  # Uses python 3.6+ string interpolation
  window.geometry(f'{animation_window_width}x{animation_window_height}')
  return window

We then create a function to create the animation canvas and attach it to the main window,

# Create a canvas for animation and add it to main window
def create_animation_canvas(window):
  canvas = tkinter.Canvas(window)
  canvas.configure(bg="black")
  canvas.pack(fill="both", expand=True)
  return canvas

Let us now create a function to create and animate a circle in an infinite loop. We use the create_oval method to create a circle(ball) with specified radius and draw it on canvas. We move the ball until it reaches a boundary and then we reverse the direction of the ball. Note the use of move method of canvas which lets us move a drawing in the canvas to another location. Also note the use of python array unpacking to get the location of the ball.

# Create and animate ball in an infinite loop
def animate_ball(window, canvas,xinc,yinc):
  ball = canvas.create_oval(animation_ball_start_xpos-animation_ball_radius,
            animation_ball_start_ypos-animation_ball_radius,
            animation_ball_start_xpos+animation_ball_radius,
            animation_ball_start_ypos+animation_ball_radius,
            fill="blue", outline="white", width=4)
  while True:
    canvas.move(ball,xinc,yinc)
    window.update()
    time.sleep(animation_refresh_seconds)
    ball_pos = canvas.coords(ball)
    # unpack array to variables
    xl,yl,xr,yr = ball_pos
    if xl < abs(xinc) or xr > animation_window_width-abs(xinc):
      xinc = -xinc
    if yl < abs(yinc) or yr > animation_window_height-abs(yinc):
      yinc = -yinc

Finally let us call all the functions in order to run our animation,

# The actual execution starts here
animation_window = create_animation_window()
animation_canvas = create_animation_canvas(animation_window)
animate_ball(animation_window,animation_canvas, animation_ball_min_movement, animation_ball_min_movement)

Full code of the python animation demo using tkinter is given below. This can be easily extended to a bat and ball game if you know event handling in tkinter. Save the following code in "tkinter-draw-demo.py" file and then run the command "python3 tkinter-draw-demo.py" to see the animation.

import tkinter
import time

# width of the animation window
animation_window_width=800
# height of the animation window
animation_window_height=600
# initial x position of the ball
animation_ball_start_xpos = 50
# initial y position of the ball
animation_ball_start_ypos = 50
# radius of the ball
animation_ball_radius = 30
# the pixel movement of ball for each iteration
animation_ball_min_movement = 5
# delay between successive frames in seconds
animation_refresh_seconds = 0.01

# The main window of the animation
def create_animation_window():
  window = tkinter.Tk()
  window.title("Tkinter Animation Demo")
  # Uses python 3.6+ string interpolation
  window.geometry(f'{animation_window_width}x{animation_window_height}')
  return window

# Create a canvas for animation and add it to main window
def create_animation_canvas(window):
  canvas = tkinter.Canvas(window)
  canvas.configure(bg="black")
  canvas.pack(fill="both", expand=True)
  return canvas

# Create and animate ball in an infinite loop
def animate_ball(window, canvas,xinc,yinc):
  ball = canvas.create_oval(animation_ball_start_xpos-animation_ball_radius,
            animation_ball_start_ypos-animation_ball_radius,
            animation_ball_start_xpos+animation_ball_radius,
            animation_ball_start_ypos+animation_ball_radius,
            fill="blue", outline="white", width=4)
  while True:
    canvas.move(ball,xinc,yinc)
    window.update()
    time.sleep(animation_refresh_seconds)
    ball_pos = canvas.coords(ball)
    # unpack array to variables
    xl,yl,xr,yr = ball_pos
    if xl < abs(xinc) or xr > animation_window_width-abs(xinc):
      xinc = -xinc
    if yl < abs(yinc) or yr > animation_window_height-abs(yinc):
      yinc = -yinc

# The actual execution starts here
animation_window = create_animation_window()
animation_canvas = create_animation_canvas(animation_window)
animate_ball(animation_window,animation_canvas, animation_ball_min_movement, animation_ball_min_movement)