How to Integrate Typesense Search Engine in a Nodejs application
Joshua Evuetapha
Posted on December 1, 2021
Tried building an application that requires efficient search? Maybe an online store or library catalog system?
It is hard to build search engines that are typo tolerant, effective and efficient. A typographical error could make a search return nothing even though the requested item is on the database.
Typesense could save you and your app users from such stress as you would not need to spend time building a search engine. And your users can effectively use the search feature in your application which would give them a great user experience.
Typesense is an open-source typo-tolerant search engine for developers, developed to reduce the time to market for apps that require effective and efficient search.
In this article, we will cover the following:
- Setting up Typesense Cloud
- Setting up our nodejs app
- Initializing the client
- Creating a Typesense Collection
- Setting up the express app
- Adding item to our collection
- Searching our collection
Setting up Typesense Cloud
You can use Typesense by either installing its docker image on your server or using the Typesense cloud hosting solution, which is the easiest way to get started with it, so we are using this option. Click Here to get started and sign in with Github.
Once authenticated, follow these steps.
- Scroll down and launch a cluster wait for about 4 to 6 minutes.
- Click on Generate API Keys. It will download a text file containing credentials needed to authenticate our app with Typesense cloud.
Setting Up the Nodejs App
Follow these steps, if you have Nodejs installed on your system if you don't download the latest version here and follow the steps.
npm init
Install the following packages express
, typesense
and nodemon
by running the following command
npm i express typesense nodemon
Add "dev": "nodemon app.js"
to the script part of the package.json file.
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js"
},
After these are done, setup the project structure to look like this.
📦express-typesense-app
┣ 📂Typesense
┃ ┣ 📜bookCollection.js
┃ ┗ 📜client.js
┣ 📜app.js
┣ 📜package.json
┗ 📜package-lock.json
Initializing the client
Navigate to the Typesense
Folder, paste codes below in the client.js
file, The first line imports Typesense
into our code, then we create a Typesense Client
instance, this instance receives an object of configurations, needed to authenticate our app with Typesense, next we export this client
so it will be available for other files. Fill in the information gotten from the text file downloaded when you generated API keys, since we are running on the backend and we want to have write access use the Admin API Key.
const Typesense = require('typesense')
const client = new Typesense.Client({
nodes: [{
host: 'your-typesense-node-gotten-from-type-sense-cloud', // For Typesense Cloud use xxx.a1.typesense.net
port: '443', // For Typesense Cloud use 443
protocol: 'https' // For Typesense Cloud use https
}],
apiKey: 'your-typesense-admin-api-key-gotten-from-type-sense-cloud',
connectionTimeoutSeconds: 5
})
module.exports = client
Creating a Typesense Collection
Typesense, a collection is a group of related documents, by are like tables in relational a database. When we create a collection, we give it a name and describe the fields that will be indexed when a document is added to the collection.
For each field, we define its name, type
, and whether it's a facet
field. A facet field allows us to cluster the search results into categories.
We also define a default_sorting_field
that determines how the results must be sorted when no sort_by
clause is provided. In this case, books that have more ratings will be ranked higher. This line of code client.collections().create(booksSchema)
create the book collection from the book schema.
This code will throw an error if the collection already exists, to prevent the app from this crashing handle the Error, by calling the error callback. as done in the code below
err => {}
.
const booksSchema = {
'name': 'books',
'fields': [
{'name': 'title', 'type': 'string' },
{'name': 'authors', 'type': 'string[]', 'facet': true },
{'name': 'image_url', 'type': 'string' },
{'name': 'publication_year', 'type': 'int32', 'facet': true },
{'name': 'ratings_count', 'type': 'int32' },
{'name': 'average_rating', 'type': 'float' }
],
'default_sorting_field': 'ratings_count'
}
client.collections().create(booksSchema)
.then( data => {
}, err => {
});
Setting up the express server
Create app.js
on the root directory of the application, we import the express
this is needed to create an express server, line 2 imports the Typesense client
this client will be used to make requests to Typesense, line 3 creates the book Collection if it doesn't exist.
const express = require('express');
const client= require('./Typesense/client');
require('./Typesense/bookCollection')
Here we create an express app, the next two lines of codes attach the middleware needed for the app to receive post data from post request.
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
Searching for books in our collection
This route handles GET requests to localhost:3000/search?q=
, the first line of code in this route get the user search input from the q
query, the second line builds the search object searchParameters
, from the search object we see that we are querying our books by its title
and sorting by ratings_count
in descending order, res.send(searchResults)
sends the search results to the client.
app.get('/search', (req, res) => {
const { q } = req.query;
const searchParameters = {
'q' : q,
'query_by' : 'title',
'sort_by' : 'ratings_count:desc'
}
client.collections('books')
.documents()
.search(searchParameters)
.then(function (searchResults) {
res.send(searchResults)
}, err => { res.send(error) } )
});
Adding data to book collection
This route handles POST request to localhost:3000/add-book
, the first line of code get the body of the post request, which in this case is the book we want to add to our collection client.collections('books').documents().create(book)
add the book to our collection. res.send(data)
sends the book data to the client.
app.post('/add-book', (req, res) => {
const book = req.body;
client.collections('books').documents().create(book).then(data => {
res.send(data)
}, err => {
res.send(err)
})
});
This codeblock runs the server on port 3000
const port = process.env.PORT || 3000;
const server = app.listen(port, () => {
console.log(App running on port </span><span class="p">${</span><span class="nx">port</span><span class="p">}</span><span class="s2">...
);
});
Adding Item to our Collection
I will be using Postman to test this app, if you are new to Postman, click here to download it, set up a workspace, and create a collection.
I added 3 books to the book collection, titled How to use Typesense in a Nodejs application
, I want to Dance
, Best Dance Move
with the following ratings respectively 4.55, 3.55, 4.35.
Searching for Item in our Collection
Searching for a book titled Best Dance Moves, Noticed, I deliberately made errors in the spelling by searching Bezt Dense Movee
and Typesense returns Two books that contain the word Dance in its title.
Searching for a "Harry Potter" which is not in our book collection returns zero items.
Conclusion
In this article, we talk about Typesense and how to get started with Typesense cloud, connecting to Typesense cloud, we created a typesense collection. We used the Typesense javascript library, this library works also works on Web Browsers, when used on Web Browser, use the search API key that doesn't grant write access. Typesense supports other languages click here to learn about them.
Using Postman to test our application we saw that Typesense is very typo tolerant, easy to use, and fast.
Posted on December 1, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.