One of my favorite activities is traveling and exploring the world. You know that feeling of discovering a new place and thinking, "How have I not been here before?" It's with that sensation that I'm always motivated to seek out new places to discover. Often, when searching for a place to stay, we're not entirely sure what we're looking for or what experiences we'd like to have. For example, we might want to rent a room in a city with a view of a castle. Finding something like that can seem difficult, right? However, there is a way to search for information accurately using Atlas Search.
In this tutorial, we will learn to build an application in Kotlin that utilizes full-text search in a database containing thousands of Airbnb listings. We'll explore how we can find the perfect accommodation that meets our specific needs.
Video Version
Here is a video version of this article if you prefer to watch.
Demonstration
To achieve our goal, we will create a Kotlin Spring Boot application that communicates with MongoDB Atlas using the Kotlin Sync Driver.
The application will use a pre-imported database in Atlas called sample_airbnb, utilizing the listingsAndReviews collection, which contains information about various Airbnbs.
To identify the best Airbnb listings, we will create an endpoint that returns information about these listings. This endpoint will use the summary field from the collection to perform a full-text search with the fuzzy parameter in text operator. Additionally, we will filter the documents based on a minimum number of reviews, utilizing the search functionalities provided by Atlas Search.
Atlas Search is a feature in MongoDB Atlas that provides powerful and flexible search capabilities for your data. It integrates with Apache Lucene, enabling advanced text analysis, custom scoring, and result highlighting. This allows you to build sophisticated search functionality directly within your MongoDB applications.
To utilize Atlas Search effectively, we will focus on three key operators: text, range, and compound. Although there are various operators available, our exploration will concentrate on these to illustrate their practical applications.
Text: This operator will be used to perform text searches within our endpoint, allowing for approximate matching and handling variations in the search terms.
Range: We will explore the range operator specifically with the gte (greater than or equals) condition for the number_of_reviews field. This will enable us to query and filter based on review counts effectively.
Compound: The compound operator will be used to combine the text fuzzy and range queries into a more complex and refined search. This will demonstrate how to merge multiple criteria for more sophisticated search functionality.
While this article will not delve deeply into all available operators, those interested in a more comprehensive exploration can refer to the MongoDB Atlas Search documentation for further details.
Load sample dataset
Before starting, you'll need to import the sample dataset, which includes several databases and collections, like the Airbnb list. After setting up your cluster, just click on "Database" in the left menu and choose "Load sample dataset," as shown in the image:
Fig: Loading Dataset in MongoDB Atlas.
If everything goes smoothly, after the import, you will see our
databases and collections displayed as shown in the image.
Fig: MongoDB Atlas with imported databases and collections.
Creating the Atlas Search index
After importing the collections, the next step is to create an index for the Airbnb collection. To do this, select "Database" from the side menu under “Deployment,” go to the "Atlas Search" tab, and click on "JSON Editor," as shown in the image:
Fig: MongoDB Atlas indicating to create an Atlas Search index.
In the next step, select the sample_airbnb database and the listingsAndReviews collection (the Airbnb collection). Then, name your index "searchPlaces":
Fig: MongoDB Atlas indicating to create an Atlas Search index Properties
Note that we are using Dynamic Mappings for simplicity, which allows
Atlas Search to automatically index the fields of supported types in
each document. For more details, I suggest checking out Define Field
Mappings
If everything goes well, the "searchPlaces" index will be created successfully, and you can view it as shown in the image below:
Fig: Screen showing the created Atlas Search Index
Testing our index in MongoDB Compass
To test our index, we need to create an aggregation pipeline. While there are various methods to test this, we will use MongoDB Compass for convenience. MongoDB Compass is a powerful GUI tool that facilitates managing and analyzing MongoDB data. It provides features to visualize schemas, build queries, and manage data through an intuitive interface.
We need to set up an aggregation pipeline to meet the following requirements:
Filter the summary field by text
Ensure a minimum number_of_reviews
Here’s the aggregation pipeline we will use for testing:
1
[
2
{
3
$search: {
4
index: "searchPlaces",
5
compound: {
6
filter: [
7
{
8
range: {
9
path: "number_of_reviews",
10
gte: 50
11
}
12
},
13
{
14
text: {
15
path: "summary",
16
query: "Istambun",
17
fuzzy: {
18
maxEdits: 2
19
}
20
}
21
}
22
]
23
}
24
}
25
},
26
{
27
$limit: 5
28
},
29
{
30
$project: {
31
_id: 0,
32
name: 1,
33
summary: 1,
34
number_of_reviews: 1,
35
price: 1,
36
street: "$address.street",
37
}
38
}
39
]
Let’s break down each stage:
$search: The $search stage uses the MongoDB Atlas Search capabilities to perform a full-text search with additional filtering.
index: "searchPlaces" specifies the search index to use. If the index name were "default," we would not need to specify it here.
compound: This allows you to combine multiple search criteria. The compound query here is used to filter the search results based on both text and range criteria.
filter: This contains an array of filter criteria applied to the search results.
range: This filters documents where the number_of_reviews field is greater than or equal to 50.
text: Text performs a full-text search on the summary field with the query "Istambun". The fuzzy option with maxEdits: 2 allows for fuzzy matching, meaning it can match terms that are similar to "Istambun" with up to two character edits (insertions, deletions, or substitutions).
$limit: This limits the number of documents returned by the query to 5. Using a limit is essential to maintain performance.
$project: This specifies which fields to include or exclude in the final result.
Simply run this pipeline to obtain the results. See:
Fig: MongoDB Compass with an executed aggregation pipeline
Building a Kotlin application
Our application will be developed in Kotlin with Spring. It’s important to note that we will not be using Spring Data. Instead, we will use the Kotlin Sync Driver, which is specialized for communication between the application and MongoDB. The goal of our application is simple:
Provide an endpoint that allows us to make requests and communicate with MongoDB Atlas.
Great, we have defined our MongoConfig class, which will use the values from application.properties. Now, create the class AirbnbEntity within the resources package:
As you can see, the method expects a query string and an int minNumberReviews and returns a list of AirbnbEntity. This list is generated through an aggregation pipeline, which consists of three stages:
Search stage: Utilizes the $search operator to filter documents based on the query and the minimum number of reviews.
Limit stage: Restricts the result set to a maximum number of documents.
Projection stage: Specifies which fields to include in the returned documents (this stage is optional and included here just to illustrate how to use it).
Notice: Depending on the scenario, adding stages after the $search
stage can drastically impact the application's performance. For more
details, refer to our docs on performance
considerations.
Creating a service
To continue with our project, let's create a domain package with two classes. The first will be our Airbnb.
In this tutorial, we built a Kotlin-based Spring Boot application that uses MongoDB Atlas Search to find Airbnb listings efficiently. We demonstrated how to create a search index and implement an aggregation pipeline for filtering and searching data.
While we focused on fuzzy matching and review count filtering, MongoDB Atlas Search offers many other powerful features, such as custom scoring and advanced text analysis.
Exploring these additional capabilities can further enhance your search functionality and provide even more refined results. The example source code used in this series is available on GitHub.