Explore Developer Center's New Chatbot! MongoDB AI Chatbot can be accessed at the top of your navigation to answer all your MongoDB questions.

Join us at AWS re:Invent 2024! Learn how to use MongoDB for AI use cases.
MongoDB Developer
MongoDB
plus
Sign in to follow topics
MongoDB Developer Centerchevron-right
Developer Topicschevron-right
Productschevron-right
MongoDBchevron-right

Using MongoDB Atlas Triggers to Summarize Airbnb Reviews with OpenAI

Pavel Duchovny4 min read • Published Oct 31, 2023 • Updated Oct 31, 2023
AINode.jsChange StreamsJavaScriptMongoDB
Facebook Icontwitter iconlinkedin icon
Rate this tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
In the realm of property rentals, reviews play a pivotal role. MongoDB Atlas triggers, combined with the power of OpenAI's models, can help summarize and analyze these reviews in real-time. In this article, we'll explore how to utilize MongoDB Atlas triggers to process Airbnb reviews, yielding concise summaries and relevant tags.
AI review UI and tags.
This article is an additional feature added to the hotels and apartment sentiment search application developed in Leveraging OpenAI and MongoDB Atlas for Improved Search Functionality.

Introduction

MongoDB Atlas triggers allow users to define functions that execute in real-time in response to database operations. These triggers can be harnessed to enhance data processing and analysis capabilities. In this example, we aim to generate summarized reviews and tags for a sample Airbnb dataset.
Our original data model has each review embedded in the listing document as an array:
1"reviews": [ { "_id": "2663437",
2"date": { "$date": "2012-10-20T04:00:00.000Z" }, \
3"listing_id": "664017",
4 "reviewer_id": "633940",
5"reviewer_name": "Patricia",
6"comments": "I booked the room at Marinete's apartment for my husband. He was staying in Rio for a week because he was studying Portuguese. He loved the place. Marinete was very helpfull, the room was nice and clean. \r\nThe location is perfect. He loved the time there. \r\n\r\n" },
7 { "_id": "2741592",
8"date": { "$date": "2012-10-28T04:00:00.000Z" },
9"listing_id": "664017",
10 "reviewer_id": "3932440",
11"reviewer_name": "Carolina",
12"comments": "Es una muy buena anfitriona, preocupada de que te encuentres cómoda y te sugiere que actividades puedes realizar. Disfruté mucho la estancia durante esos días, el sector es central y seguro." }, ... ]

Prerequisites

  • App Services application (e.g., application-0). Ensure linkage to the cluster with the Airbnb data.
  • OpenAI account with API access.
Open AI Key Open AI Key

Secrets and Values

  1. Navigate to your App Services application.
  2. Under "Values," create a secret named openAIKey with your OPEN AI API key. Secrets and Values
  3. Create a linked value named OpenAIKey and link to the secret.

The trigger code

The provided trigger listens for changes in the sample_airbnb.listingsAndReviews collection. Upon detecting a new review, it samples up to 50 reviews, sends them to OpenAI's API for summarization, and updates the original document with the summarized content and tags. Atlas Trigger Configuration
Please notice that the trigger reacts to updates that were marked with "process" : false flag. This field indicates that there were no summary created for this batch of reviews yet.
Example of a review update operation that will fire this trigger:
1listingsAndReviews.updateOne({"_id" : "1129303"}, { $push : { "reviews" : new_review } , $set : { "process" : false" }});

Sample reviews function

To prevent overloading the API with a large number of reviews, a function sampleReviews is defined to randomly sample up to 50 reviews:
1function sampleReviews(reviews) {
2 if (reviews.length <= 50) {
3 return reviews;
4 }
5
6 const sampledReviews = [];
7 const seenIndices = new Set();
8
9 while (sampledReviews.length < 50) {
10 const randomIndex = Math.floor(Math.random() * reviews.length);
11 if (!seenIndices.has(randomIndex)) {
12 seenIndices.add(randomIndex);
13 sampledReviews.push(reviews[randomIndex]);
14 }
15 }
16
17 return sampledReviews;
18}

Main trigger logic

The main trigger logic is invoked when an update change event is detected with a "process" : false field.
1exports = async function(changeEvent) {
2 // A Database Trigger will always call a function with a changeEvent.
3 // Documentation on ChangeEvents: https://mongodb.prakticum-team.ru/docs/manual/reference/change-events
4
5 // This sample function will listen for events and replicate them to a collection in a different Database
6function sampleReviews(reviews) {
7// Logic above...
8 if (reviews.length <= 50) {
9 return reviews;
10 }
11 const sampledReviews = [];
12 const seenIndices = new Set();
13
14 while (sampledReviews.length < 50) {
15 const randomIndex = Math.floor(Math.random() * reviews.length);
16 if (!seenIndices.has(randomIndex)) {
17 seenIndices.add(randomIndex);
18 sampledReviews.push(reviews[randomIndex]);
19 }
20 }
21
22 return sampledReviews;
23}
24
25 // Access the _id of the changed document:
26 const docId = changeEvent.documentKey._id;
27 const doc= changeEvent.fullDocument;
28
29
30 // Get the MongoDB service you want to use (see "Linked Data Sources" tab)
31 const serviceName = "mongodb-atlas";
32 const databaseName = "sample_airbnb";
33 const collection = context.services.get(serviceName).db(databaseName).collection(changeEvent.ns.coll);
34
35 // This function is the endpoint's request handler.
36 // URL to make the request to the OpenAI API.
37 const url = 'https://api.openai.com/v1/chat/completions';
38
39 // Fetch the OpenAI key stored in the context values.
40 const openai_key = context.values.get("openAIKey");
41
42 const reviews = doc.reviews.map((review) => {return {"comments" : review.comments}});
43
44 const sampledReviews= sampleReviews(reviews);
45
46 // Prepare the request string for the OpenAI API.
47 const reqString = `Summerize the reviews provided here: ${JSON.stringify(sampledReviews)} | instructions example:\n\n [{"comment" : "Very Good bed"} ,{"comment" : "Very bad smell"} ] \nOutput: {"overall_review": "Overall good beds and bad smell" , "neg_tags" : ["bad smell"], pos_tags : ["good bed"]}. No explanation. No 'Output:' string in response. Valid JSON. `;
48 console.log(`reqString: ${reqString}`);
49
50 // Call OpenAI API to get the response.
51
52 let resp = await context.http.post({
53 url: url,
54 headers: {
55 'Authorization': [`Bearer ${openai_key}`],
56 'Content-Type': ['application/json']
57 },
58 body: JSON.stringify({
59 model: "gpt-4",
60 temperature: 0,
61 messages: [
62 {
63 "role": "system",
64 "content": "Output json generator follow only provided example on the current reviews"
65 },
66 {
67 "role": "user",
68 "content": reqString
69 }
70 ]
71 })
72 });
73
74 // Parse the JSON response
75 let responseData = JSON.parse(resp.body.text());
76
77 // Check the response status.
78 if(resp.statusCode === 200) {
79 console.log("Successfully received code.");
80 console.log(JSON.stringify(responseData));
81
82 const code = responseData.choices[0].message.content;
83 // Get the required data to be added into the document
84 const updateDoc = JSON.parse(code)
85 // Set a flag that this document does not need further re-processing
86 updateDoc.process = true
87 await collection.updateOne({_id : docId}, {$set : updateDoc});
88
89
90 } else {
91 console.error("Failed to generate filter JSON.");
92 console.log(JSON.stringify(responseData));
93 return {};
94 }
95};
Key steps include:
  • API request preparation: Reviews from the changed document are sampled and prepared into a request string for the OpenAI API. The format and instructions are tailored to ensure the API returns a valid JSON with summarized content and tags.
  • API interaction: Using the context.http.post method, the trigger sends the prepared data to the OpenAI API.
  • Updating the original document: Upon a successful response from the API, the trigger updates the original document with the summarized content, negative tags (neg_tags), positive tags (pos_tags), and a process flag set to true.
Here is a sample result that is added to the processed listing document:
1"process": true,
2"overall_review": "Overall, guests had a positive experience at Marinete's apartment. They praised the location, cleanliness, and hospitality. However, some guests mentioned issues with the dog and language barrier.",
3"neg_tags": [ "language barrier", "dog issues" ],
4"pos_tags": [ "great location", "cleanliness", "hospitality" ]
Once the data is added to our documents, providing this information in our VUE application is as simple as adding this HTML template:
1<div v-if="listing.overall_review" class="overall-review" >
2 <b>Overall Review (ai based) :</b> {{ listing.overall_review }}
3 <div v-for="tag in listing.pos_tags" >
4 <span class="badge-pos">{{tag}}</span>
5 </div>
6 <div v-for="tag in listing.neg_tags" >
7 <span class="badge-neg">{{tag}}</span>
8 </div>
9 </div>

Conclusion

By integrating MongoDB Atlas triggers with OpenAI's powerful models, we can efficiently process and analyze large volumes of reviews in real-time. This setup not only provides concise summaries of reviews but also categorizes them into positive and negative tags, offering valuable insights to property hosts and potential renters.
Questions? Comments? Let’s continue the conversation over in our community forums.

Facebook Icontwitter iconlinkedin icon
Rate this tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Related
Code Example

Reactive Java Spring Boot with MongoDB


Apr 02, 2024 | 5 min read
Tutorial

Exploring the Advanced Search Capabilities With MongoDB Atlas Search


Aug 20, 2024 | 6 min read
Article

Document Validation for Polymorphic Collections


Oct 01, 2024 | 6 min read
Tutorial

Create a RESTful API With .NET Core and MongoDB


Sep 11, 2024 | 8 min read
Table of Contents
  • Introduction