Overview
In this blog post we will explore LiteDB by implementing common operations and understanding a bit more about NoSQL.
LiteDB is an embedded .NET NoSQL database, inspired by MongoDB. It’s simple and light, storing data as documents that are similar to JSON objects containing key-value pairs. As a schemaless database, LiteDB allows any data—containing individual fields and structures—to be added to the database.
Benefits of LiteDB (NoSQL)
Why use LiteDB compared to a SQL database?
Flexibility
As mentioned previously, LiteDB—being a schemaless database—allows a higher level of flexibility, being able to store incomplete data and easily change that data. This allows for more rapid development and testing.
Affordability
There is a reason NoSQL is commonly used with big data: if you have an application with millions of users using your program daily, that will probably result in a lot of GET requests to your database, adding strain and more expenses. As NoSQL databases are not normalized, concepts such as data duplication might prove beneficial.
As an example, imagine an application storing student information and their grades. If these are separate documents but we need to display the grade information alongside student information, then the grade information could be added twice in the database, once in its own document and once in the student document. While this goes against normalization if we were to use SQL, with NoSQL it can cut your costs in half.
Scaling
NoSQL offers horizontal scalability: thanks to its flexible nature, it's able to spread across multiple servers allowing you to add cheap servers when needed.
Implementation
In this section, I'll show common operations you might need in a CRUD application.
Let's start with importing the necessary depedencies:
#r "nuget: LiteDB.FSharp, 2.16.0"
open LiteDB
open LiteDB.FSharp
open LiteDB.FSharp.Extensions
Intialize the database and our types:
let mapper = FSharpBsonMapper()
let db = new LiteDatabase("school.db", mapper)
type Course = Astrophysics | Physics
type Grade = Pass | Fail
type Student =
{ Id: int
Name: string
Course: Course
Grade: Grade }
As you can see, in this example we will be handling student information in a simple LiteDB database.
Now let's refer to the collection of students in the DB, this is what we will use for manipulating and displaying the student information:
let students = db.GetCollection<Student>("students")
Let's create some records defining the students:
let student1 =
{ Id = 1
Name = "Jane Doe"
Course = Astrophysics
Grade = Pass }
let student2 =
{ Id = 2
Name = "John Bruke"
Course = Physics
Grade = Fail }
let student3 =
{ Id = 3
Name = "Yuri Gagari"
Course = Astrophysics
Grade = Fail }
Let's add the students to our DB:
students.Insert(student1)
students.Insert(student2)
students.Insert(student3)
Note: Data inserted into DB is persistent, meaning once these students are added you will not be allowed to add them again, otherwise you will get an error.
Let's do some common operations.
Search:
// Find student by index
let firstStudent = students.FindById(1)
// Get the students studying Astrophysics
let astrophysicsStudents = students.findMany <@ fun student -> student.Course = Astrophysics @>
We can verify it worked by displaying the values like this:
printfn $"{firstStudent.Name}"
astrophysicsStudents
|> Seq.map (fun student -> student.Name)
|> Seq.iter (printfn "%s")
Update and delete:
// Update
student2.Name = "John Doe"
students.Update(student2)
// Delete
students.Delete(1)
students.Delete(2)
students.Delete(3)
Please checkout Zaid's repo for more information on how to use LiteDB with F#. Their great work was the inspiration for writing the demo shown above 🙂
Conclusion
This blog post was a short introduction to LiteDB and how to use with F#. We also explored the benefits of NoSQL and specified some use cases. Hopefully you found this information useful and made you consider exploring LiteDB yourself 😊