<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Roman Right</title>
    <description>The latest articles on Forem by Roman Right (@romanright).</description>
    <link>https://forem.com/romanright</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F583640%2F75c5e669-ee7b-4068-93a7-155ad88f90b0.jpg</url>
      <title>Forem: Roman Right</title>
      <link>https://forem.com/romanright</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/romanright"/>
    <language>en</language>
    <item>
      <title>Studio 3T Performance Suite: How to Identify and Resolve Performance Bottlenecks in MongoDB</title>
      <dc:creator>Roman Right</dc:creator>
      <pubDate>Thu, 01 Feb 2024 11:01:00 +0000</pubDate>
      <link>https://forem.com/romanright/studio-3t-performance-suite-how-to-identify-and-resolve-performance-bottlenecks-in-mongodb-328f</link>
      <guid>https://forem.com/romanright/studio-3t-performance-suite-how-to-identify-and-resolve-performance-bottlenecks-in-mongodb-328f</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In today's data-driven landscape, the performance of databases is not just a technical concern but a pivotal factor in the success of any application. MongoDB, renowned for its scalability and flexibility, is no exception. However, as systems grow in complexity and data volume, performance bottlenecks can emerge, significantly impacting user experience and system reliability. This article delves into harnessing the power of Studio 3T, a comprehensive tool suite for MongoDB, to optimize database performance. We will explore how Studio 3T's features, like the Query Profiler, Index Manager and Visual Explain, can be used to identify and resolve common performance issues, ensuring that your MongoDB database runs efficiently and effectively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsvwjha2ilssghmyu9uya.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsvwjha2ilssghmyu9uya.png" alt="Studio 3T Logo" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Query Profiler
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The Heart of Performance Analysis&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Query Profiler in Studio 3T stands as a vital instrument for enhancing MongoDB's performance. Integrating the capabilities of MongoDB's Database Profiler, it offers an in-depth examination of your database operations. This tool is essential in illuminating both the execution time and patterns of your queries, providing a surprising degree of useful insight.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Spotting Slow Queries: A Practical Scenario&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Consider a smart home system that processes a myriad of device events for a wide customer base. Each event, whether from a security camera or a smart thermostat, results in a data entry. Envision this system bogged down by a particular query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customer_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ObjectId('&lt;/span&gt;&lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="err"&gt;b&lt;/span&gt;&lt;span class="mi"&gt;69&lt;/span&gt;&lt;span class="err"&gt;ed&lt;/span&gt;&lt;span class="mi"&gt;094&lt;/span&gt;&lt;span class="err"&gt;c&lt;/span&gt;&lt;span class="mi"&gt;014&lt;/span&gt;&lt;span class="err"&gt;b&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;d&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="err"&gt;fa&lt;/span&gt;&lt;span class="mi"&gt;889&lt;/span&gt;&lt;span class="err"&gt;')&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"device_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"security_camera"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event_details.alert_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sound_detected"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the absence of efficient indexing, the execution time of this query stretches to an excruciating 2.5 seconds, an unacceptable delay in a real-time monitoring scenario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffaejt3itnmcstautx8cd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffaejt3itnmcstautx8cd.png" alt="Query Profiler displaying the slow query" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this instance, the Query Profiler adeptly identifies the tardy query. Its graphical display reveals vital statistics, such as execution time and frequency, which are instrumental in understanding the query's impact on the system's overall performance. This leads us to two crucial components of the Query Profiler:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query Code Window&lt;/strong&gt;: This section displays the query in question, aiding developers in pinpointing the problematic segment in the code base. It serves as a direct link between the observed performance issue and the specific part of the code that may require optimization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fueobkx6ti8vuefxhz7ev.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fueobkx6ti8vuefxhz7ev.png" alt="Query Code Window displaying the slow query" width="489" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Validating Improvements using Visual Explain
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Demystifying Query Execution with Visual Insights&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Visual Explain in Studio 3T is an invaluable tool for comprehensively understanding the execution process of MongoDB queries. It provides a detailed graphical representation of how queries are executed and the impact of different indexes on these processes. In addition to the visualisation, Visual Explain provides runtime stats for each step, showing how much data is being transferred and how long it has taken. It is available in the main query tools in Studio 3T and now also in its own window in the Query Profiler.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explain Plan Window&lt;/strong&gt;: Here, the profiler presents a graphical explanation of the query execution process. This visual breakdown includes various stages of the query execution, notably highlighting steps like 'collection scan.' A 'collection scan' indicates the absence of an index at a critical point, signaling a potential area for performance enhancement through indexing strategies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ln2d3p7pq6k8xnnqlbg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ln2d3p7pq6k8xnnqlbg.png" alt="Explain Plan Window displaying the slow query" width="750" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Equipped with this comprehensive analysis, developers gain the necessary insights to make informed decisions, such as refining the query or implementing the required indexes, to optimize performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimizing with the Index Manager
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Streamlining Performance through Strategic Indexing&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Index Manager in Studio 3T is a pivotal tool for optimizing query performance in MongoDB. It plays a critical role in identifying and creating indexes that can significantly reduce query execution times. By efficiently managing indexes, the Index Manager ensures that your database operations are streamlined and performant.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Case Study: Enhancing Query Speed with a Custom Index&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To illustrate, let's revisit the slow query from our smart home system scenario:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"customer_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ObjectId('&lt;/span&gt;&lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="err"&gt;b&lt;/span&gt;&lt;span class="mi"&gt;69&lt;/span&gt;&lt;span class="err"&gt;ed&lt;/span&gt;&lt;span class="mi"&gt;094&lt;/span&gt;&lt;span class="err"&gt;c&lt;/span&gt;&lt;span class="mi"&gt;014&lt;/span&gt;&lt;span class="err"&gt;b&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;d&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="err"&gt;fa&lt;/span&gt;&lt;span class="mi"&gt;889&lt;/span&gt;&lt;span class="err"&gt;')&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"device_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"security_camera"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event_details.alert_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sound_detected"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To address the 2.5-second delay in query execution, we can use the Index Manager to create a compound index. This index would be on the fields &lt;code&gt;customer_id&lt;/code&gt;, &lt;code&gt;device_type&lt;/code&gt;, and &lt;code&gt;event_details.alert_type&lt;/code&gt;. By doing so, we are aligning the index directly with the query's structure, allowing MongoDB to retrieve the necessary data more efficiently.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbmklqbeufyv2divtjmx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbmklqbeufyv2divtjmx.png" alt="New Index Creation in Index Manager" width="663" height="663"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this screenshot, we see the Index Manager showcasing the creation of the new compound index. The fields &lt;code&gt;customer_id&lt;/code&gt;, &lt;code&gt;device_type&lt;/code&gt;, and &lt;code&gt;event_details.alert_type&lt;/code&gt; are highlighted, demonstrating how the index aligns with the query structure.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Observing the Impact of the New Index on Execution Time&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With the new index created via the Index Manager, we used Visual Explain to evaluate its effect on our query. This tool graphically displays the modified execution plan. The key alteration is the switch from a collection scan to an index scan, reflecting a more efficient data retrieval method.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqg7u0sxcz6fs51gbwrol.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqg7u0sxcz6fs51gbwrol.png" alt="Visual Explain displaying the optimized query" width="800" height="481"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Visual Explain interface highlights this change, emphasizing the faster index scan. Remarkably, the total execution time of the query is now shown as 0ms, a significant decrease from the original 2.5 seconds, demonstrating the substantial impact of the optimization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nm5ucdy6k53xc1sifrz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7nm5ucdy6k53xc1sifrz.png" alt="Visual Explain displaying the optimized query" width="656" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking Results in the Query Profiler
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Confirming Optimization Success&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The final step in our optimization journey involves revisiting the Query Profiler in Studio 3T. This tool, which initially helped us identify the slow query, now serves to confirm the effectiveness of our optimization strategies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3ccso9s4r7rw3uhin40.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3ccso9s4r7rw3uhin40.png" alt="Query Profiler displaying the optimized query" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Query Profiler display, we observe a significant change. The previously sluggish query, after optimization, is conspicuously absent from recent query executions. We only see historical instances from before the optimization. This indicates that the query, now executing in under a millisecond, is no longer a bottleneck in performance. This marked improvement is a strong endorsement of our indexing strategy and the comprehensive optimization process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Harnessing Studio 3T for Peak MongoDB Performance&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In conclusion, this guide has demonstrated the power and utility of Studio 3T's tools in identifying and resolving performance issues within MongoDB databases. Starting with the Query Profiler, we identified a performance bottleneck. We then utilized the Index Manager to strategically create an index, drastically improving query execution times. The Visual Explain feature provided us with a clear, graphical representation of this improvement, showing a reduction in execution time to under a millisecond. Finally, our return to the Query Profiler confirmed the elimination of the slow query from recent executions, validating the effectiveness of our optimization efforts.&lt;/p&gt;

&lt;p&gt;This journey underscores the importance of a systematic approach to database performance tuning. By leveraging Studio 3T’s comprehensive suite of tools, developers and database administrators can ensure their MongoDB databases are running efficiently and effectively. I encourage readers to apply these methodologies to their own databases, ensuring they remain high-performing and robust in handling data-intensive operations.&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>performance</category>
      <category>database</category>
      <category>learning</category>
    </item>
    <item>
      <title>MongoDB Performance Tools</title>
      <dc:creator>Roman Right</dc:creator>
      <pubDate>Wed, 10 Jan 2024 11:00:00 +0000</pubDate>
      <link>https://forem.com/romanright/mongodb-performance-tools-da0</link>
      <guid>https://forem.com/romanright/mongodb-performance-tools-da0</guid>
      <description>&lt;p&gt;MongoDB is a powerful database, capable of handling a wide range of use cases. However, to extract the best performance from MongoDB, understanding and utilizing a range of supportive tools is key. This guide introduces a variety of tools that can enhance MongoDB's performance, irrespective of their origin.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkghkfb1txo2gkig1a45z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkghkfb1txo2gkig1a45z.png" alt="Toolbelt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Mongostat&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Mongostat is an invaluable tool for real-time monitoring of MongoDB's performance. It offers snapshots of database activity, enabling developers to swiftly assess and address performance challenges. By examining the mongostat output from your MongoDB instance, we can glean crucial insights.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;High Activity&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgobca2fku0cmfpndnl8k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgobca2fku0cmfpndnl8k.png" alt="Mongostat High Activity Output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first screenshot displays a high level of database activity, with &lt;code&gt;insert&lt;/code&gt;, &lt;code&gt;query&lt;/code&gt;, and &lt;code&gt;update&lt;/code&gt; operations at approximately 1300-1400 operations per second. This signifies a system under heavy load, managing a significant volume of data transactions. Notably, the &lt;code&gt;dirty&lt;/code&gt; and &lt;code&gt;used&lt;/code&gt; percentages remain low, suggesting efficient memory usage with the current working set.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Low Activity&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh5jsybrun2dj5kit5730.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh5jsybrun2dj5kit5730.png" alt="Mongostat Low Activity Output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In contrast, the second screenshot reveals a marked decrease in operation rates, with counts falling to 10-48 operations per second for &lt;code&gt;insert&lt;/code&gt;, &lt;code&gt;query&lt;/code&gt;, and &lt;code&gt;update&lt;/code&gt;. This reduction is noted under consistent load test conditions, where both the number of connections and client-side requests remained unchanged. Despite a steady influx of client requests, the database appears to have become a bottleneck. Possible causes include resource saturation, inefficient query execution, or suboptimal indexing, all leading to prolonged response times and diminished throughput.&lt;/p&gt;

&lt;p&gt;In this screenshot, the &lt;code&gt;qrw&lt;/code&gt; (queued read and write operations) and &lt;code&gt;arw&lt;/code&gt; (active read and write operations) columns are particularly telling. An increase in these values suggests a build-up of operations waiting to be processed, confirming the bottleneck scenario. The &lt;code&gt;qrw&lt;/code&gt; metric alerts us to the number of operations in queue, highlighting potential delays in processing, while &lt;code&gt;arw&lt;/code&gt; shows the number of actively processing operations, providing insight into the current load on the database.&lt;/p&gt;

&lt;p&gt;Observations from mongostat are critical in real-world contexts, as they enable the identification of heavy load periods and sudden performance downturns. Such data is instrumental for developers in diagnosing issues, whether that involves delving into specific queries, reevaluating indexing strategies, or adjusting resource allocation for better load management.&lt;/p&gt;

&lt;p&gt;The real-time feedback provided by mongostat is essential for maintaining optimal database performance, particularly in scenarios involving high traffic. Continuous monitoring of these metrics empowers developers to proactively manage their database environment, ensuring efficient and smooth operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;MongoDB Compass&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;MongoDB Compass provides an intuitive graphical interface to visualize and understand the structure of your database collections. This is particularly useful in identifying inefficiencies and potential areas for optimization.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Collection Structure Overview&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffo994uivvujh5sdffrln.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffo994uivvujh5sdffrln.png" alt="Compass Collection Structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This screenshot presents an overview of the collection's structure. A notable aspect here is the &lt;code&gt;address_history&lt;/code&gt;field. It's an array of documents, each containing 5 nested fields. The array length varies significantly across documents, with the minimum length being 0, an average of 7.56, and a maximum of 20.&lt;/p&gt;

&lt;p&gt;Such variability in array length can be a critical factor in the collection's performance. Larger array sizes, especially when they exceed the average by a considerable margin, can lead to increased document size and potentially slower query performance. This insight can guide us in restructuring the data, perhaps by normalizing the collection or implementing more efficient indexing strategies.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Detailed View of Address History Field&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5p2f01bfbyou9pf3t9yc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5p2f01bfbyou9pf3t9yc.png" alt="Address History Field"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second screenshot offers a detailed view of the &lt;code&gt;address_history&lt;/code&gt; field. It breaks down the frequency of various cities and other sub-fields within the address history. This level of detail can reveal trends or anomalies in the data distribution.&lt;/p&gt;

&lt;p&gt;For example, if certain city names appear disproportionately often, it might indicate data skewness, which can impact the performance of queries filtered by city names. Similarly, understanding the distribution of other sub-fields helps in identifying redundant or rarely used data, paving the way for data cleanup and optimization.&lt;/p&gt;

&lt;p&gt;Through these screenshots, MongoDB Compass effectively demonstrates its capability to provide deep insights into your data's structure and composition. This information is vital for making informed decisions about database optimization and restructuring, ensuring efficient data storage and retrieval.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Mongotop&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Mongotop is an essential tool in the MongoDB suite, offering real-time insights into the read and write activities of database collections. It's instrumental in identifying resource-intensive collections and guiding optimization efforts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Before Indexing&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpavelbhrk204q9hx5v6w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpavelbhrk204q9hx5v6w.png" alt="Mongotop output before indexing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During a recent analysis with mongotop, the &lt;code&gt;articles.users&lt;/code&gt; collection was closely monitored. The initial data presented a notable level of activity:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total time: 4168 milliseconds&lt;/li&gt;
&lt;li&gt;Read operations: 1994 milliseconds&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Write operations: 2174 milliseconds&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;After Indexing&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvnmmaznqx9fpoc0h2lw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvnmmaznqx9fpoc0h2lw.png" alt="Mongotop output after indexing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, after indexing and a subsequent observation period, there was a remarkable shift in the operational times:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total time: 599 milliseconds&lt;/li&gt;
&lt;li&gt;Read operations: 290 milliseconds&lt;/li&gt;
&lt;li&gt;Write operations: 308 milliseconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This marked decrease in both read and write times is a clear indicator of enhanced efficiency, likely due to the implementation of the index. The balanced distribution between read and write operations post-optimization suggests a more efficient handling of database tasks.&lt;/p&gt;

&lt;p&gt;The ability of mongotop to provide such real-time, granular data is invaluable for database administrators and developers. It not only allows them to monitor the immediate impact of optimizations but also helps in identifying areas requiring further attention. This tool is crucial for maintaining and improving database performance, ensuring optimal operation and efficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Studio 3T&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For many MongoDB enthusiasts, Studio 3T is the toolbelt that feels like an extension of their own hands. A treasure trove of features, Studio 3T is crafted to augment MongoDB's native capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Query Profiler&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Studio 3T's Query Profiler stands as a key instrument for optimizing MongoDB performance. Specializing in identifying and improving slow queries, this tool uses MongoDB's Database Profiler to gather detailed insights about query execution times and patterns, thus equipping developers with actionable information.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Spotting Slow Queries&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Far6halclvzgflpfczj26.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Far6halclvzgflpfczj26.png" alt="Slow aggregation query found"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The provided screenshot showcases the Query Profiler's adeptness at highlighting a slow query. For instance, a &lt;code&gt;$lookup&lt;/code&gt; aggregation without an index initially results in a significant delay, taking about 10 seconds. Such extended execution times can drastically affect database performance, particularly in high-load environments.&lt;/p&gt;

&lt;p&gt;The profiler efficiently displays vital statistics such as execution time and frequency, offering a clear view of a query's impact. In addition to providing the full runtime JSON script, it also separates out the query code itself. Developers can now not only understand the causer of the slowdown, but they can then remedy the problem there and then,  either by adding or removing an index or by editing the query itself before rerunning and checking for improvement.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Optimization via Indexing&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpoy64xktgd5r1edlnuen.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpoy64xktgd5r1edlnuen.png" alt="Slow aggregation query doesn't appear more"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Query Profiler is instrumental in the optimization process. By adding an index to relevant fields, like &lt;code&gt;product_ids&lt;/code&gt; in the &lt;code&gt;orders&lt;/code&gt; collection, the execution time for the same &lt;code&gt;$lookup&lt;/code&gt; aggregation is notably reduced. The profiler confirms this enhancement, as the query no longer appears as a performance bottleneck.&lt;/p&gt;

&lt;p&gt;This improvement, evident in the screenshot, illustrates the profiler's effectiveness in not just identifying but also in validating the impact of optimization strategies.&lt;/p&gt;

&lt;p&gt;In conclusion, Studio 3T's Query Profiler is a vital asset for MongoDB developers, simplifying the often intricate task of database optimization. It facilitates a clear and efficient workflow for detecting performance issues and validating the efficacy of implemented solutions. Through its use, MongoDB instances can be fine-tuned for optimal performance, ensuring that they operate not only effectively but also at their peak efficiency.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Visual Explain&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Every MongoDB query has an execution plan. It's like the route your GPS suggests when you're driving. Now, imagine if you could visually trace this route to identify traffic jams or shortcuts? Studio 3T's Visual Explain does exactly that—it offers a graphical representation of the MongoDB execution plan. By displaying how queries run, it makes it infinitely easier to spot bottlenecks.&lt;/p&gt;

&lt;p&gt;You can find more information about this tool in the first article of the series: &lt;a href="https://dev.to/romanright/setting-the-stage-unraveling-mongodb-query-performance-3cde"&gt;Setting the Stage: Unraveling MongoDB Query Performance&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Aggregation Editor&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Aggregation in MongoDB is an art and a science. Complex aggregation queries can, at times, be performance guzzlers. Studio 3T’s Aggregation Editor offers a respite. With a stage-by-stage interface, it simplifies the process of building, debugging, and most importantly, optimizing aggregation queries.&lt;/p&gt;

&lt;p&gt;More information about this tool can be found in the second article of the series: &lt;a href="https://dev.to/romanright/identifying-mongodb-performance-pitfalls-5302"&gt;Identifying MongoDB Performance Pitfalls&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To maximize MongoDB's performance, a combination of various tools is essential. Tools like MongoDB Compass, Mongostat, Mongotop, and Studio 3T each contribute uniquely to understanding, monitoring, and enhancing database performance. By utilizing these tools effectively, developers and database administrators can ensure optimal operation and efficiency of their MongoDB instances.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Crafting Efficient MongoDB Queries</title>
      <dc:creator>Roman Right</dc:creator>
      <pubDate>Thu, 30 Nov 2023 11:00:00 +0000</pubDate>
      <link>https://forem.com/romanright/crafting-efficient-mongodb-queries-284f</link>
      <guid>https://forem.com/romanright/crafting-efficient-mongodb-queries-284f</guid>
      <description>&lt;p&gt;MongoDB, a leading database in the NoSQL domain, is not just about storing data—it's about harnessing it efficiently. Dive into the heart of its query system, understand its inner workings, and discover strategies to transform the way you interact with and retrieve your data.&lt;/p&gt;

&lt;h3&gt;
  
  
  MongoDB's Response Mechanism: The Power of the &lt;code&gt;explain()&lt;/code&gt; Method.
&lt;/h3&gt;

&lt;p&gt;Imagine sending a message out into the void, hoping for an answer but never quite knowing if your message was received, let alone understood. That's what querying without feedback feels like. With MongoDB's &lt;code&gt;explain()&lt;/code&gt; method, we get to peek behind the curtain, understanding how our queries fare in the grand scheme of things.&lt;/p&gt;

&lt;h4&gt;
  
  
  What's this &lt;code&gt;explain()&lt;/code&gt; magic?
&lt;/h4&gt;

&lt;p&gt;At its core, &lt;code&gt;explain()&lt;/code&gt; provides insights into the execution of MongoDB operations. By analyzing the output, developers can decode the database's decision-making process, getting a step-by-step walkthrough of how a query is executed. This doesn't just make you feel like a database wizard, but it also arms you with the knowledge to optimize queries for better performance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fia3ty17g03ot4dz4chov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fia3ty17g03ot4dz4chov.png" alt="Professor explains a theorem"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Deciphering the Talkback
&lt;/h4&gt;

&lt;p&gt;From the troves of information that &lt;code&gt;explain()&lt;/code&gt; returns, a few fields stand out in their importance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;executionStats&lt;/strong&gt;: This provides an overview of how your query was executed. Here you'll see details about the number of documents scanned, the number of documents returned, and how long the query took.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;executionStages&lt;/strong&gt;: A closer look into the mechanics of your query's execution. It can reveal whether your query did a full collection scan (&lt;code&gt;COLLSCAN&lt;/code&gt;) or if it used an index (&lt;code&gt;IXSCAN&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;queryPlanner&lt;/strong&gt;: Offers an insight into MongoDB's thought process. What strategy did it decide was best for your query? Did it consider multiple strategies before choosing one?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To bring these abstract concepts to life, let's consider a simple query where we wish to fetch all products in category "A" from our fictional collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;collection.find(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we use the &lt;code&gt;explain()&lt;/code&gt; method without an index on the "category" field, the output highlights that MongoDB had to scan every single document in the collection to find matches. This is evident in the &lt;code&gt;executionStages&lt;/code&gt; field with the value &lt;code&gt;COLLSCAN&lt;/code&gt; and &lt;code&gt;totalDocsExamined&lt;/code&gt; being 1,000,000.&lt;/p&gt;

&lt;p&gt;However, when an index on the &lt;code&gt;category&lt;/code&gt; field is introduced and the same query is analyzed with explain(), the difference is night and day. Instead of COLLSCAN, we now see IXSCAN in the executionStages field, indicating that the database smartly used the index. Moreover, the totalDocsExamined drastically reduces to 199,916, showcasing the immense power of indexing. It's important to remember why such improvements in query performance are valuable: querying less data means using less time to do it. This efficiency translates into freeing up compute cycles, allowing other work to proceed more smoothly. Consequently, there's a direct impact on database hosting costs, as reduced processing time and resource usage can lead to significant cost savings.&lt;/p&gt;

&lt;h4&gt;
  
  
  Bridging Understanding for Efficiency
&lt;/h4&gt;

&lt;p&gt;Understanding the feedback from MongoDB is akin to listening intently in a conversation. By focusing on what MongoDB is 'saying', we can adjust our questions (queries) to be more in tune with the database's strengths. Indexing, for instance, becomes a clear pathway to optimization once we've grasped how powerful it can be from the &lt;code&gt;explain()&lt;/code&gt; outputs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mastering Indexes in MongoDB: Balancing Adaptability and Performance.
&lt;/h3&gt;

&lt;p&gt;Imagine trying to find a particular book in a colossal library. Without any categorization or system, the task would be daunting and time-consuming. Similarly, in the grand library of MongoDB data, indexes serve as our guiding system, directing our queries with precision and speed. We've just witnessed how a well-placed index can turn an exhaustive COLLSCAN into a much more performant IXSCAN. But what's behind this magic? Let's journey into the heart of MongoDB indexing.&lt;/p&gt;

&lt;h4&gt;
  
  
  A Deep Dive into Indexing's Role
&lt;/h4&gt;

&lt;p&gt;In essence, an index in MongoDB is a data structure that holds a subset of the collection's data in an easy-to-traverse form. This subset, ordered by the value of a specific field or set of fields, allows MongoDB to avoid scanning every document in a collection when searching for data. As seen in our earlier example with product categories, indexing can greatly enhance search efficiency.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Colorful Palette of Indexes in MongoDB
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmjtefuhlco4zmzkbykk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmjtefuhlco4zmzkbykk.png" alt="A women is trying to choose a vase"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MongoDB offers a properly rich set of index types and options for anyone seriously interested in query tuning. Each index type is crafted to serve specific use-cases, ensuring efficient querying and data retrieval. Here's a deep dive into these index types, explaining their purpose, how they work internally, and their primary use-cases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Single Field&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: To support efficient searches on individual fields.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How it works&lt;/strong&gt;: This index type creates a B-tree structure on a single field, enabling fast lookups.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use-case&lt;/strong&gt;: Suited for situations where queries primarily focus on one field, like looking up users by their username.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Compound&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: To handle queries that combine multiple fields.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How it works&lt;/strong&gt;: This index spans multiple fields within a document. A B-tree structure is maintained for the combination of these fields.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use-case&lt;/strong&gt;: Useful when querying on conditions that involve multiple fields, like finding orders based on both customer ID and product ID.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Multikey&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: To index array data effectively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How it works&lt;/strong&gt;: Indexes each individual element of an array.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use-case&lt;/strong&gt;: Suited for situations where queries target specific array values, like filtering products by tags.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Text&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: To provide efficient full-text search capabilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How it works&lt;/strong&gt;: It tokenizes strings and stores them as an inverted index, making text searches faster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use-case&lt;/strong&gt;: Suitable for applications that require text search functionality, like searching for articles containing specific words or phrases.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Geospatial&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: To facilitate queries based on geographical locations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How it works&lt;/strong&gt;: Uses a special indexing mechanism to efficiently store and query data based on geographic coordinates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use-case&lt;/strong&gt;: Ideal for location-based services, like finding nearby restaurants or calculating distances between points.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Hashed&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Primarily to support sharding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How it works&lt;/strong&gt;: It hashes the field's value and then indexes this hash, ensuring an even distribution of data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use-case&lt;/strong&gt;: Suitable for databases that use sharding to distribute data across multiple servers or clusters.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Wildcard&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: To offer flexibility by indexing fields dynamically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How it works&lt;/strong&gt;: Instead of indexing specified fields, it indexes all fields, ensuring no field is left unindexed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use-case&lt;/strong&gt;: Useful in scenarios where the structure of documents is dynamic or not well-defined in advance.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Sparse&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: To conserve memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How it works&lt;/strong&gt;: Only includes documents where the indexed field is present, ensuring the index remains lightweight.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use-case&lt;/strong&gt;: Ideal for collections where only some documents contain the indexed field, like optional attributes in user profiles.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;TTL (Time-to-Live)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: To automate data pruning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How it works&lt;/strong&gt;: Monitors the indexed timestamp field and removes documents once they've existed past a specified duration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use-case&lt;/strong&gt;: Perfect for data with a natural expiration, such as session data or temporary logs.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Partial&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: To ensure resource efficiency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How it works&lt;/strong&gt;: Only indexes a subset of documents, based on a defined filter condition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use-case&lt;/strong&gt;: Designed for large collections where only a specific fraction of documents are relevant for indexing, like indexing only 'active' user accounts.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Each of these indexes plays a crucial role in ensuring MongoDB's versatility and performance. By understanding the strengths and ideal use-cases for each type, developers can craft optimized, responsive, and resource-efficient applications.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Delicate Balance: Tradeoffs of Indexing
&lt;/h4&gt;

&lt;p&gt;However, with great power comes great responsibility. Indexing isn't a silver bullet. While they speed up read operations, they introduce overheads:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Write Operation Delays&lt;/strong&gt;: Every time data is written or updated in the collection, the corresponding index also needs an update. This can introduce latency, especially if multiple indexes exist for a collection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Space Overheads&lt;/strong&gt;: Indexes consume disk space. In some scenarios, especially with multiple compound indexes, the indexes' size can exceed the size of the data itself.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the world of databases, there's always a balancing act between read and write efficiency and the resource footprint. The art lies in strategically creating indexes based on the specific needs of the application and the query patterns, ensuring that the benefits outweigh the costs.&lt;/p&gt;

&lt;h3&gt;
  
  
  MongoDB's Best Practices: Streamlining Data Operations with Native Techniques
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Paging Through Your Data: From Clunky Steps to Graceful Strides
&lt;/h4&gt;

&lt;p&gt;Pagination is one of those ubiquitous data operations that sounds simple but can be tricky to implement efficiently, especially when dealing with copious amounts of data. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traditional Approach: Skip and Limit&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A conventional method involves using &lt;code&gt;skip()&lt;/code&gt; and &lt;code&gt;limit()&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;collection.find(&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="err"&gt;).skip(&lt;/span&gt;&lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="err"&gt;).limit(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method skips the first 50,000 documents and then fetches the next 100. It works perfectly for smaller datasets. But as the amount of data grows, the performance can degrade. Imagine skipping over a million records to get to the next set. Imagine trying to jump to the last chapter of a book but having to flip through every single page to get there. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Efficient Turn: Range Queries&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A more efficient strategy involves using range queries. Instead of skipping records, you position your query based on a certain field's range.&lt;/p&gt;

&lt;p&gt;Let's say we're working with a timestamp. Instead of skipping over documents, we'd pull records that have a timestamp greater than the last one we've processed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;collection.find(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$gt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;lastKnownTimestamp&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="err"&gt;).limit(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we've bypassed the clunky skip and are now taking graceful strides through the data, enhancing the efficiency manifold.&lt;/p&gt;

&lt;h4&gt;
  
  
  Textual Battles: Regex vs. Text Search
&lt;/h4&gt;

&lt;p&gt;Text searches are pivotal for any database, and MongoDB offers two primary tools: regular expressions (regex) and text search.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Original Approach: Text Search&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;MongoDB's text search is designed to be nuanced, taking into account language-specific stop words and stemming. However, MongoDB mandates that a text search step must be the primary operation in an aggregation pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;collection.find(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;$text:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;$search:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"coffee"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Efficient Route: Regex&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you can replace the text search with a regex, especially in scenarios where a match query reduces the number of documents to be scanned, the regex will be more efficient. This is because it can be applied post the match step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;collection.aggregate(&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;$match:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"productName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$exists"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;}}},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;$match:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"productName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;/coffee/i&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the regex operates on a reduced set of documents due to the preceding match step, resulting in a more efficient query.&lt;/p&gt;

&lt;h4&gt;
  
  
  Choosing Wisely: The $in Operator vs. the $or Operator
&lt;/h4&gt;

&lt;p&gt;When we're dealing with selecting documents based on multiple criteria, MongoDB presents us with two operators: &lt;code&gt;$in&lt;/code&gt; and &lt;code&gt;$or&lt;/code&gt;. Both serve a purpose, but there's a marked difference in how they impact performance. Let's embark on a journey to understand when and why you might favor one over the other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Original Approach: Using $or&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider this scenario: you want to fetch products from categories 'A' and 'B' but only those priced at $500 or less. Using the &lt;code&gt;$or&lt;/code&gt; operator, your query would resemble:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;db.getCollection(&lt;/span&gt;&lt;span class="s2"&gt;"products"&lt;/span&gt;&lt;span class="err"&gt;).find(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"$or"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$lte"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$lte"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;).explain()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, MongoDB is essentially evaluating two distinct conditions. For every document, it questions, "Is this a product from category 'A' with a price of $500 or less? If not, is it from category 'B' and similarly priced?". Now, this method might be efficient for modest datasets, but with an increasing volume of data, the two conditions being checked independently can consume more time and resources. If there's no index to assist, the process can further lag.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Streamlined Method: Using $in&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Enter the more succinct &lt;code&gt;$in&lt;/code&gt; operator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;db.getCollection(&lt;/span&gt;&lt;span class="s2"&gt;"products"&lt;/span&gt;&lt;span class="err"&gt;).find(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$in"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$lte"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;).explain()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This refined query is essentially an encapsulation of the previous &lt;code&gt;$or&lt;/code&gt; conditions. But what sets &lt;code&gt;$in&lt;/code&gt; apart? When MongoDB encounters the &lt;code&gt;$in&lt;/code&gt; operator and an index exists on the &lt;code&gt;category&lt;/code&gt; field, it can quickly pinpoint the documents with categories "A" and "B". Instead of evaluating two distinct conditions like &lt;code&gt;$or&lt;/code&gt;, it checks the indexed values for the presence of both "A" and "B" categories, ensuring a more streamlined retrieval.&lt;/p&gt;

&lt;p&gt;The choice between &lt;code&gt;$in&lt;/code&gt; and &lt;code&gt;$or&lt;/code&gt; might appear nuanced at first glance, but these subtleties can profoundly influence database performance. In our endeavor to master the MongoDB vernacular, recognizing such distinctions enables us to converse more efficiently with our data repositories. Knowledge is power, and in this context, it's also speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Decoding Query Performance with Studio 3T's IntelliShell
&lt;/h3&gt;

&lt;p&gt;Studio 3T is one of the foremost MongoDB GUIs and provides a myriad of tools to facilitate seamless database interaction, including the IntelliShell, which gives developers the ability to write, edit, and execute MongoDB commands in a shell-like environment.&lt;/p&gt;

&lt;p&gt;When trying to decipher the efficiency of different MongoDB operations, the &lt;code&gt;.explain()&lt;/code&gt; method becomes crucial. Using Studio 3T's IntelliShell tool, we can run &lt;code&gt;.explain()&lt;/code&gt; on queries to garner insights into how MongoDB processes them. Let's dive deep into this by comparing the &lt;code&gt;$in&lt;/code&gt; vs. &lt;code&gt;$or&lt;/code&gt; operators using the provided examples.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step-by-Step Guide:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. Launch IntelliShell&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;In Studio 3T, click on the IntelliShell button to open a new tab where you can input MongoDB commands.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;![Studio 3T screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/my2m2gc5tlyp7qti1jxa.png)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;2. Execute the &lt;code&gt;$in&lt;/code&gt; Query&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
       &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;category&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$in&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]},&lt;/span&gt; 
       &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$lte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;explain&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upon executing, you'll get a JSON response. The key sections to pay attention to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;winningPlan&lt;/code&gt;: This section reveals the optimized plan chosen by MongoDB to execute your query. As seen in the provided output, the chosen plan uses a &lt;code&gt;FETCH&lt;/code&gt; stage to filter the &lt;code&gt;price&lt;/code&gt;, and then an &lt;code&gt;IXSCAN&lt;/code&gt; stage to use the index on the &lt;code&gt;category&lt;/code&gt; field.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;indexName&lt;/code&gt;: This confirms that the query is using the &lt;code&gt;category_1&lt;/code&gt; index, signifying the use of the indexed field which boosts query performance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq0iuc2bf2iajxa6zq0h5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq0iuc2bf2iajxa6zq0h5.png" alt="Studio 3T screenshot"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Execute the &lt;code&gt;$or&lt;/code&gt; Query&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;   &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
       &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$or&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;category&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$lte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;category&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$lte&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
       &lt;span class="p"&gt;]&lt;/span&gt;
   &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;explain&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;$or&lt;/code&gt; query response:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;winningPlan&lt;/code&gt; section shows the &lt;code&gt;SUBPLAN&lt;/code&gt; stage, which is essentially MongoDB evaluating multiple query plans. It then uses an &lt;code&gt;OR&lt;/code&gt; stage to combine the results of two independent &lt;code&gt;FETCH&lt;/code&gt; and &lt;code&gt;IXSCAN&lt;/code&gt; stages.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Notably, even though the &lt;code&gt;$or&lt;/code&gt; query uses the same &lt;code&gt;category_1&lt;/code&gt; index, it evaluates each condition in the &lt;code&gt;$or&lt;/code&gt; array separately. This distinction highlights why the &lt;code&gt;$in&lt;/code&gt; operator is generally more efficient than the &lt;code&gt;$or&lt;/code&gt; operator for this specific use-case.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi3az3wc4y57rxznl1cl9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi3az3wc4y57rxznl1cl9.png" alt="Studio 3T screenshot"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Comparative Analysis&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Both queries utilize the &lt;code&gt;category_1&lt;/code&gt; index. However, the execution is different.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$in&lt;/code&gt; offers a streamlined approach with a singular &lt;code&gt;FETCH&lt;/code&gt; and &lt;code&gt;IXSCAN&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In contrast, &lt;code&gt;$or&lt;/code&gt; separately evaluates each condition leading to two separate &lt;code&gt;FETCH&lt;/code&gt; and &lt;code&gt;IXSCAN&lt;/code&gt; operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Conclusion:
&lt;/h4&gt;

&lt;p&gt;Using the IntelliShell tool in Studio 3T, we can vividly see the under-the-hood differences in how MongoDB executes the &lt;code&gt;$in&lt;/code&gt; and &lt;code&gt;$or&lt;/code&gt; operations. For the given example, the &lt;code&gt;$in&lt;/code&gt; operation proves to be more efficient as it employs a singular indexed scan for multiple values. On the other hand, the &lt;code&gt;$or&lt;/code&gt; operation separately assesses each condition, adding overhead to the query processing.&lt;/p&gt;

&lt;p&gt;Understanding these nuances empowers developers to write optimized queries, ensuring swifter response times and efficient use of resources. Remember, the devil is in the details, and with Studio 3T's IntelliShell, you can unveil these crucial details.&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>performance</category>
      <category>beginners</category>
      <category>database</category>
    </item>
    <item>
      <title>Identifying MongoDB Performance Pitfalls</title>
      <dc:creator>Roman Right</dc:creator>
      <pubDate>Thu, 26 Oct 2023 12:25:01 +0000</pubDate>
      <link>https://forem.com/romanright/identifying-mongodb-performance-pitfalls-5302</link>
      <guid>https://forem.com/romanright/identifying-mongodb-performance-pitfalls-5302</guid>
      <description>&lt;p&gt;MongoDB's reputation in the NoSQL community is built on its query optimization capabilities. In the previous article, we explored how MongoDB queries work and how to use native optimization techniques to improve performance. Understanding these concepts is vital for crafting efficient queries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqkivn5rz5n8ka1jo6pp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkqkivn5rz5n8ka1jo6pp.png" alt="Investigator with a huge clok-like machine"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, even experienced developers sometimes face challenges that slow down performance. To achieve the best performance, we need to know not only how MongoDB queries work but also how to avoid common problems that can waste time and resources. Knowledge helps us find better efficiency and speed. Let's explore this together, highlighting common challenges and discussing how to tackle them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The N+1 Problem: Unnecessary Resource Overhead
&lt;/h2&gt;

&lt;p&gt;Imagine a scenario. Your application needs to fetch data about a set of users and their respective posts from the database. A common approach involves making one query to retrieve the users and then, for each user, making additional queries to fetch their posts. While it may seem straightforward, this N+1 query problem slyly drains the vitality from your application's performance.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Example of the N+1 problem in MongoDB&lt;/span&gt;
&lt;span class="nx"&gt;users&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the above code, for every user fetched from the &lt;code&gt;users&lt;/code&gt; collection, an additional query is made to the &lt;code&gt;posts&lt;/code&gt; collection to retrieve their posts, resulting in N+1 queries (where N is the number of users). It’s a classic trap, with each additional query incrementally throttling the speed and efficiency, making the application progressively sluggish, and devouring server resources as it goes.&lt;/p&gt;

&lt;p&gt;The antidote? Batch the queries, letting MongoDB handle multiple requests in a single go, minimizing the back-and-forth and ensuring the resources are judiciously used.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Batching queries to resolve the N+1 problem&lt;/span&gt;
&lt;span class="nx"&gt;userIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;userPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userIds&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By utilizing the &lt;code&gt;$in&lt;/code&gt; operator, the second query now fetches all posts for the user IDs in a single sweep, effectively countering the N+1 query problem and conserving your application's robustness and vitality. The art lies in striking a balance, ensuring that the strategies employed enhance performance, not stifle it, keeping the MongoDB queries in the fast lane, smoothly sailing towards optimal efficiency.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Silent Delay: Unpacking the Effect of Missing Indexes
&lt;/h2&gt;

&lt;p&gt;When working with MongoDB, even well-crafted queries can experience performance drops if the right indexes are missing. Without these indexes, MongoDB is forced to perform a collection scan, meaning it goes through every document in the collection to find the needed data. While this might be okay for small datasets, it can cause delays as the data grows.&lt;/p&gt;

&lt;p&gt;Look at this typical query:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;brand&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Apple&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Without an index on &lt;code&gt;brand&lt;/code&gt;, MongoDB must scan through the entire orders collection, which may not be effective for large datasets.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfgnl30iarhd22am9qq9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfgnl30iarhd22am9qq9.png" alt="Without Index"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But, adding an index can greatly improve query speed:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Indexing the brand field&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;brand&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With this index, MongoDB can quickly find relevant documents, reducing unneeded processing time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnp6yc37vtgfa23fbwmvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnp6yc37vtgfa23fbwmvw.png" alt="With And Without Index"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Still, indexing isn't about just adding them everywhere. Too many or poorly set up indexes can actually slow things down. It's vital to carefully choose which fields to index based on how queries are made, and to keep an eye on index size and memory use to get the best results.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hidden Bumps on the Road: Other Overlooked Pitfalls
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Unoptimized Aggregation Pipelines
&lt;/h3&gt;

&lt;p&gt;Take the case where you're aggregating documents to find the total sales for each item. Without optimization, the aggregation pipeline processes every document in the collection.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// An unoptimized aggregation query&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sales&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;totalSales&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$sum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$amount&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The query above groups the &lt;code&gt;sales&lt;/code&gt; collection by the &lt;code&gt;item&lt;/code&gt; field and calculates the total &lt;code&gt;amount&lt;/code&gt;. It might work efficiently for smaller datasets but can become a bottleneck as the data grows because it processes each document in the collection.&lt;/p&gt;

&lt;p&gt;An enhancement would be to use the &lt;code&gt;$match&lt;/code&gt; stage early in the pipeline to filter documents based on certain criteria. For instance, suppose you’re only interested in calculating total sales for items that have sold at least once in the past week. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Optimized aggregation query&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sales&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;lastSoldDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$gte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2023-09-23&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$item&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;totalSales&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$sum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$amount&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By introducing &lt;code&gt;$match&lt;/code&gt;, the aggregation pipeline first filters out the documents that do not meet the criteria (items sold in the past week), thereby reducing the number of documents that the &lt;code&gt;$group&lt;/code&gt; stage has to process. This optimized pipeline ensures that only relevant documents are processed, boosting the efficiency and speed of the aggregation operation. &lt;/p&gt;

&lt;p&gt;In this example, the &lt;code&gt;$match&lt;/code&gt; stage serves to narrow down the data that is processed in the subsequent stages, demonstrating a typical scenario where the strategic arrangement of pipeline stages contributes to enhanced performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ignoring Sharding for Large Datasets
&lt;/h3&gt;

&lt;p&gt;Another unnoticed pitfall is the neglect of sharding for large datasets. Sharding distributes the data across multiple servers, ensuring that the database can scale beyond the limits of a single server. Ignoring it could lead to unbalanced and overloaded systems, tarnishing performance and speed.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Implement sharding&lt;/span&gt;
&lt;span class="nx"&gt;sh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enableSharding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;database&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;sh&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shardCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;database.collection&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;shardKey&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With these simple commands, sharding is enabled for the specified database and collection, providing a vital boost for handling vast datasets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Overlooking Connection Pooling
&lt;/h3&gt;

&lt;p&gt;A further overlooked detail is not utilizing connection pooling. Opening a new database connection every time is not only expensive in terms of resources, but it also adds unnecessary latency.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// Use connection pooling&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MongoClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;poolSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here, a connection pool of size 50 is created, reusing existing connections and averting the overhead of establishing a new one each time.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Studio 3T Spotlight&lt;/strong&gt;: Fine-Tuning Aggregation Pipeline Efficiency
&lt;/h2&gt;

&lt;p&gt;I'd like to pick up one of the pitfalls we discussed earlier and show you how Studio 3T can help you improve the performance.&lt;/p&gt;

&lt;p&gt;Imagine we have a service that collects anonymized user click data. Each document in the dataset might resemble the following:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ObjectId(&lt;/span&gt;&lt;span class="s2"&gt;"6531f27d8a57e4c3a95738fd"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;450&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"y"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;320&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2023-10-17T14:08:59.000+0000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;



&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Where x and y represent the click coordinates on the page. The task is to aggregate this data to find regions (or bins) of the page that receive the most clicks.&lt;/p&gt;

&lt;p&gt;Here's the initial aggregation pipeline:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Original&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Pipeline&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"$project"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"binX"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$floor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$divide"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"$x"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;]}},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"binY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$floor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$divide"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"$y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;]}}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"$group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"binX"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$binX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"binY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$binY"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$sum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$sort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Preparation
&lt;/h3&gt;

&lt;p&gt;Start by opening the Aggregation Editor for the "clicks" collection. This is where you will input the aggregation pipeline steps, setting the stage for further analysis and optimization. This initial setup is crucial for ensuring that the pipeline runs efficiently, and it aids in quickly identifying any potential issues that may arise. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8v34gf2doqm3umzua4lq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8v34gf2doqm3umzua4lq.png" alt="Aggregation Editor"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Identifying the Problem and Implementing the Solution
&lt;/h3&gt;

&lt;p&gt;With the pipeline set, it’s time to pinpoint the bottleneck. The &lt;code&gt;Explain&lt;/code&gt; button is a powerful tool that provides a detailed breakdown of the pipeline’s execution, highlighting the time taken at each stage.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/JL1AKJtgIrA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run the &lt;code&gt;Explain&lt;/code&gt; for the aggregation.&lt;/li&gt;
&lt;li&gt;Detect the slowdown at the &lt;code&gt;$group&lt;/code&gt; step, with a 9-second execution time.&lt;/li&gt;
&lt;li&gt;Introduce the $sample step before the aggregation, drastically improving the performance by reducing the data to a manageable sample size.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgngvqa2623gckw43hy61.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgngvqa2623gckw43hy61.png" alt="Optimized pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
  Pipeline
  &lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Optimized&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Pipeline&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$sample"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"$project"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"binX"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$floor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$divide"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"$x"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;]}},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"binY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$floor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$divide"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"$y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;]}}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"$group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"binX"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$binX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"binY"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$binY"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"sampledCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$sum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$sort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"sampledCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"$limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;You can find the script that generates the experiment data &lt;a href="https://github.com/roman-right/clicks" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's important to note that sampling can quickly process large datasets but adds some approximation. It works best on extensive data where a random sample gives a representative snapshot of the full dataset.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In the world of MongoDB, achieving optimal performance can sometimes be a challenge. But with the right information and methods, these challenges become opportunities for improving efficiency and speed. The strategies discussed here help protect your MongoDB operations from unnecessary delays and resource use. As you keep using and refining these methods, your MongoDB tasks will not only sustain but flourish, offering top performance and helping your projects succeed effortlessly. Remain alert and informed, and let each step on this journey be a move towards continuous excellence in MongoDB.&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>database</category>
      <category>learning</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Detective de'Code and the Dueling Dishes</title>
      <dc:creator>Roman Right</dc:creator>
      <pubDate>Wed, 11 Oct 2023 18:50:43 +0000</pubDate>
      <link>https://forem.com/romanright/detective-decode-and-the-dueling-dishes-1igj</link>
      <guid>https://forem.com/romanright/detective-decode-and-the-dueling-dishes-1igj</guid>
      <description>&lt;h2&gt;
  
  
  The Call
&lt;/h2&gt;

&lt;p&gt;On a foggy evening, Louis de'Code was deeply focused in the green glow of his terminal when an unexpected notification jolted him. His old-fashioned, ringtone echoed through his dimly-lit office: "Gelátoz needs your help!" Gelátoz, the talk-of-the-town food delivery app, had become synonymous with the annual Feast of Fables - a playful holiday celebrating the most treasured culinary tales from around the world.&lt;/p&gt;

&lt;p&gt;The message was clear and urgent: "Detective! Gelátoz hangs and hiccups just as our customers are finalizing their festive orders. And just our luck, due to the new privacy law that forbids retaining user food preferences, the logs—rich with food content—had to be deleted! Feast of Fables is days away, and this hiccup could turn our grand celebration into a grand fiasco."&lt;/p&gt;

&lt;p&gt;A holiday where mythic dishes took center stage, Feast of Fables was Gelátoz's crowning achievement, and a malfunction now would not only spell a gastronomical disaster but also might just put the final nail in their digital coffin. The stakes were high, and the clock was ticking.&lt;/p&gt;

&lt;p&gt;With his keen senses tingling, detective de'Code felt the weight of this crisis. Clearing the code clutter on his screen, he mentally geared up for a deep dive into the realm of Gelátoz, where culinary wonders met code. The game was on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech Trio
&lt;/h2&gt;

&lt;p&gt;In the heart of the city, the grand Gelátoz headquarters resembled an architectural masterpiece, where vintage aesthetics embraced the throbbing pulse of modern tech innovation. Inside this wonder, culinary fantasies transmuted into digital commands, awaiting their journey to patrons eagerly anticipating the Feast of Fables.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b38IpIUU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://roman-right.dev/articles/series/detective-de-code/detective-de-code-and-the-dueling-dishes/assets/office.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b38IpIUU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://roman-right.dev/articles/series/detective-de-code/detective-de-code-and-the-dueling-dishes/assets/office.webp" alt="Gelátoz" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As de'Code made his entry, the symphony of coding keystrokes and server hums hinted at the technological dance unfolding. Immediately, he discerned the trio that wove the tech tapestry of Gelátoz:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fiona, the Frontend Maestro&lt;/strong&gt;: Donning an artsy beret and a demeanor of fierce focus, Fiona was fluent in the poetry of React. She delicately crafted user interfaces that felt less like screens and more like tantalizing culinary presentations. When not immersed in her digital creations, Fiona lost herself to the rhythm of dance, her body painting stories in the air with grace.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Benny, the Backend Virtuoso&lt;/strong&gt;: His quirky "Life's better in Python" tee told tales of his expertise. Orchestrating the data dynamics using FastAPI, Benny ensured that the heartbeats of Gelátoz's operations always played in rhythm.  Away from the digital waves, Benny felt a deep connection to the vastness of the seas, his heart echoing the call of seafaring adventures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Alice, the Database Guardian&lt;/strong&gt;: With her serene aura, and a mug that cleverly quipped, "Keep calm and query on," Alice guarded the sanctum of Postgres. Ensuring every data point, every transaction was as meticulous as a chef's recipe, she made sure the digital ingredients always sang in harmony. In her free time, the world of chess captivated her – where she meticulously planned moves and strategies, mirroring her precision at work.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Surveying the trio and the digital masterpiece they'd crafted, detective de'Code braced himself. With a malfunctioning app, mysteriously vanished logs, and the Feast of Fables ticking closer, his plate was full. The culinary coding caper had just begun.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rhythmic Riddles
&lt;/h2&gt;

&lt;p&gt;The grand room of Gelátoz's headquarters was punctuated by the determined pacing of detective de'Code. "The culprit must lie somewhere in the path of promo dish recommendation," he mused. First stop: the Frontend - the shop window of the app. Fiona, with a nervous glance, handed him access to the console, where the notorious JavaScript snippet lay in wait.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;PromoDishDetails&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;dishId&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;dish&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setDish&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;chefDetails&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setChefDetails&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

 &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/promoDishes/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dishId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
     &lt;span class="nx"&gt;setDish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

     &lt;span class="c1"&gt;// Fetching chef details after getting the dish details&lt;/span&gt;
     &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;chefResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/chefs/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chefId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;chefData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chefResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
     &lt;span class="nx"&gt;setChefDetails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chefData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="nx"&gt;fetchData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
 &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;dishId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
     &lt;span class="nx"&gt;Dish&lt;/span&gt; &lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dish&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;br&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="nx"&gt;Promo&lt;/span&gt; &lt;span class="nx"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dish&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;promoPrice&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;br&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
     &lt;span class="nx"&gt;Chef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;chefDetails&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Examining the lines, de'Code felt the rhythm of the sequential API calls, like notes in a well-composed melody. "Sequential requests," he thought aloud. "But executed gracefully."&lt;/p&gt;

&lt;p&gt;He imagined it as a choreographed dance: a performer moves to the stage, dances, and only when the routine is done does the next performer take their turn. Each step is well-rehearsed; there's no tripping or overstepping. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y_qB1t4y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://roman-right.dev/articles/series/detective-de-code/detective-de-code-and-the-dueling-dishes/assets/fiona.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y_qB1t4y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://roman-right.dev/articles/series/detective-de-code/detective-de-code-and-the-dueling-dishes/assets/fiona.webp" alt="Fiona" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fiona sighed with relief. "So, our front-end dance is smooth?"&lt;/p&gt;

&lt;p&gt;Detective de'Code nodded, appreciating the finesse in the script. "It's not here that our villain hides. The choreography is well-executed, no step out of place."&lt;/p&gt;

&lt;h2&gt;
  
  
  Tales from the Depths
&lt;/h2&gt;

&lt;p&gt;Pivoting, Louis de'Code ventured into the darker, more enigmatic world of the backend. Like a sailor about to navigate uncharted waters, Benny, holding his code snippet, handed over the map to the next mystery.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_promo_dishes&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsyncClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MAX_RETRIES&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;SUPPLIER_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/promo"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MAX_RETRIES&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RETRY_DELAY&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;raise&lt;/span&gt;


&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/promoDishes/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_promo_dishes&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
   &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
       &lt;span class="n"&gt;dishes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;fetch_promo_dishes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dishes&lt;/span&gt;
   &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Failed to fetch promotional dishes."&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The detective's fingers trailed over the lines detailing retries, a clever system reminiscent of a sailor adjusting his course amidst changing winds and tides. "Resilient code," he admired. "Just like a captain not letting a few storms dissuade his journey, but knowing when to dock for shelter. Benny, this is masterful navigation. You've safeguarded against turbulent third-party waters."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BiMI82-i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://roman-right.dev/articles/series/detective-de-code/detective-de-code-and-the-dueling-dishes/assets/benny2.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BiMI82-i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://roman-right.dev/articles/series/detective-de-code/detective-de-code-and-the-dueling-dishes/assets/benny2.webp" alt="Benny" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Benny, beaming with a mix of pride and relief, responded, "We don't want to be those sailors who fight against a storm until their ship sinks. We adjust the sails, make a few attempts, then find safe harbor."&lt;/p&gt;

&lt;p&gt;As the backend's innocence became evident, de'Code's gaze wandered, seeking another thread. "Considering the system stalls post-order but prior to promo dish recommendation, our focus should now be on the order placement mechanism." The game was still afoot.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stalemate Standoff
&lt;/h2&gt;

&lt;p&gt;Amid the dim lighting of the server room, detective de'Code, with narrowed eyes, stared at the enigma on the screen. The cursor blinked in a rhythmic pattern, but what unfolded was nothing short of a fierce chess match between two pieces: &lt;code&gt;process_normal_order&lt;/code&gt; and &lt;code&gt;process_combo_order&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;"Notice," the detective whispered, fingers caressing the keyboard, "how these two functions handle transactions in reverse order. The devil, as they say, is in the details."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_normal_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_dish_ids&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"""
            UPDATE 
                inventory
            SET 
                stock = stock - 1
            WHERE
                id = ANY($1::int[]);
            """&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;order_dish_ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"""
            INSERT INTO
                orders (status, dish_ids)
            VALUES
                ('created', $1);
            """&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;order_dish_ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_combo_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;combo_dish_ids&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;combo_dish_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;combo_dish_ids&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;COLA_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FRIES_ID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"""
            INSERT INTO
                orders (status, dish_ids)
            VALUES 
                ('created', $1);
            """&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;combo_dish_ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"""
            UPDATE 
                inventory
            SET
                stock = stock - 1
            WHERE
                id = ANY($1::int[]);
            """&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;combo_dish_ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/placeOrder/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;place_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncpg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"combo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;process_combo_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dish_ids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;process_normal_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dish_ids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Order placed successfully!"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The room, filled with developers and stakeholders, buzzed with confusion. Alice, the database expert, stepped forward. "When two transactions compete for the same resources but in reverse order, it's a classic recipe for a deadlock. It's as if two chess players tried to checkmate each other, but their moves end up in a stalemate."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h2t2ZOAs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://roman-right.dev/articles/series/detective-de-code/detective-de-code-and-the-dueling-dishes/assets/alice3.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h2t2ZOAs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://roman-right.dev/articles/series/detective-de-code/detective-de-code-and-the-dueling-dishes/assets/alice3.webp" alt="Alice" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Detective de'Code nodded in agreement. "Exactly. In a high traffic scenario, when both functions are invoked almost simultaneously, one waits for the other indefinitely, creating a standstill - our mastermind antagonist: the deadlock."&lt;/p&gt;

&lt;h2&gt;
  
  
  Resolution Recipe
&lt;/h2&gt;

&lt;p&gt;With the problem identified, Louis de'Code, ever the genius, set forth on rectifying it. He swiftly rearranged the code, ensuring consistency in transaction order, preventing the chess pieces from getting trapped.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_dish_ids&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Let's combine the logic so that 
&lt;/span&gt;    &lt;span class="c1"&gt;# transaction order is consistent
&lt;/span&gt;    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"""
            INSERT INTO
                orders (status, dish_ids)
            VALUES
                ('created', $1);
            """&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;order_dish_ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"""
            UPDATE
                inventory
            SET
                stock = stock - 1 
            WHERE 
                id = ANY($1::int[]);
            """&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;order_dish_ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/placeOrder/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;place_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncpg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;dish_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dish_ids&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"combo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;dish_ids&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;COLA_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FRIES_ID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;process_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dish_ids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Order placed successfully!"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The room erupted in applause. Alice, impressed, remarked, "By ensuring that both types of orders follow the same transaction pattern, you've eliminated the potential for a deadlock. Brilliant!"&lt;/p&gt;

&lt;p&gt;But amidst the cheers, de'Code, ever modest, simply adjusted his hat. "It's all about ensuring the right recipe, a harmonized blend of ingredients. Tech problems, after all, are like puzzles waiting to be solved."&lt;/p&gt;

&lt;p&gt;And with that, the detective packed his toolkit. "Another tech enigma awaits," he remarked, leaving the Gelátoz team in awe, their gratitude palpable, their system more robust.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>database</category>
      <category>bug</category>
      <category>python</category>
    </item>
    <item>
      <title>Setting the Stage: Unraveling MongoDB Query Performance</title>
      <dc:creator>Roman Right</dc:creator>
      <pubDate>Wed, 27 Sep 2023 11:51:14 +0000</pubDate>
      <link>https://forem.com/romanright/setting-the-stage-unraveling-mongodb-query-performance-3cde</link>
      <guid>https://forem.com/romanright/setting-the-stage-unraveling-mongodb-query-performance-3cde</guid>
      <description>&lt;h2&gt;
  
  
  The heart of digital interactions: Why MongoDB's speed and efficiency matter.
&lt;/h2&gt;

&lt;p&gt;In our warp-speed digital age, isn't database performance more than a perk? Imagine a bustling online store during a massive sale. A lag isn't just some annoying spinner—it's missed profit.&lt;/p&gt;

&lt;p&gt;Now, picture a financial trading platform on a high-stakes day. Delays? Those could lead to significant financial repercussions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffiv9gucj3doje96hroha.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffiv9gucj3doje96hroha.png" alt="Stock exchange"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moreover, we're now in an era of real-time data analytics and machine learning, where data isn't just retrieved but also processed at lightning speeds. Real-time recommendations, fraud detection, or even simple tasks like auto-fill in forms, rely heavily on the efficiency of these databases.&lt;/p&gt;

&lt;p&gt;However, it's not just about speed. The concept of efficiency also translates to the system’s ability to handle vast amounts of data with minimal resources. As businesses grow and scale, so do their databases. Herein lies the beauty of MongoDB – its design allows it to balance the scales of speed and resource management.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgnzmd7kc0rpzsxsho86a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgnzmd7kc0rpzsxsho86a.png" alt="Performance chart"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Anatomy of a MongoDB query: Breaking it down.
&lt;/h2&gt;

&lt;p&gt;So, what makes a MongoDB query tick? Let's dive in.&lt;/p&gt;

&lt;p&gt;First, it's essential to understand that MongoDB is a NoSQL database. Unlike its relational counterparts, it uses JSON-like documents with optional schemas, meaning data can be stored in varied formats. This feature itself lends a degree of flexibility to MongoDB that is often absent in traditional databases.&lt;/p&gt;

&lt;p&gt;Every query begins with a client sending a request to the MongoDB server. This could be anything from a simple &lt;code&gt;find&lt;/code&gt; request to retrieve documents to more complex aggregate functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Namespace
&lt;/h3&gt;

&lt;p&gt;The first step in this journey is the Namespace. Think of it as a combination of the database name and the collection or index name. It's the address of sorts, directing the query where to go.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;For example, consider the following MongoDB shell command:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;usersDatabase&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userCollection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;usersDatabase.userCollection&lt;/code&gt; is the namespace.&lt;/p&gt;

&lt;h3&gt;
  
  
  Query Selector
&lt;/h3&gt;

&lt;p&gt;Once the namespace is identified, the next step is the Query Selector. This is where the conditions for the query are set. For example, if you want to find all users from a particular city, the query selector will contain parameters to match against documents in the chosen collection.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In the MongoDB shell, it might look something like this:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userCollection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;address.city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;New York&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;{"address.city": "New York"}&lt;/code&gt; is the query selector.&lt;/p&gt;

&lt;h3&gt;
  
  
  Indexes
&lt;/h3&gt;

&lt;p&gt;MongoDB is smart. Instead of scanning every document, it uses indexes to speed up the search process. If the appropriate index exists, MongoDB can locate the documents in a fraction of the time it would have otherwise taken.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;For instance, you might create an index on the city field like so:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userCollection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;address.city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Projection
&lt;/h3&gt;

&lt;p&gt;Finally, once the documents are located and retrieved, we have the Projection. This determines which fields from the documents are returned. Think of it as a spotlight on specific information, focusing on what's essential and discarding the rest.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In the MongoDB shell, a projection can be illustrated as:&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userCollection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;address.city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;New York&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;address.city&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, only the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;address.city&lt;/code&gt; fields will be returned for documents that match the query, while the &lt;code&gt;_id&lt;/code&gt; field is excluded.&lt;/p&gt;

&lt;h2&gt;
  
  
  MongoDB's thought process: Delving into query execution
&lt;/h2&gt;

&lt;p&gt;MongoDB isn't just any ordinary database that takes in a query and spits out a result. There's an intricate dance of logic, planning, and execution that takes place behind the scenes, ensuring the speedy and efficient retrieval of data.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Query Planner&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Whenever a query is issued to MongoDB, it doesn't just jump right into fetching the data. First, it takes a moment to strategize. This is the domain of the &lt;code&gt;Query Planner&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Query Planner&lt;/code&gt; assesses possible strategies to retrieve the data. If there are indexes that can be used, it evaluates each of them. Essentially, it's looking for the most efficient path, much like how a GPS navigates through various routes to determine the quickest way to your destination.&lt;/p&gt;

&lt;p&gt;During this phase, MongoDB might even execute multiple query plans concurrently, racing them against each other to figure out the fastest one.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Query Executor&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Having mapped out its strategy, MongoDB then hands over the baton to the &lt;code&gt;Query Executor&lt;/code&gt;. This component is all about action. It takes the chosen plan from the &lt;code&gt;Query Planner&lt;/code&gt; and executes it, retrieving the required documents from the collection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy6rdlay023nfned1clg6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy6rdlay023nfned1clg6.png" alt="Race"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For performance optimization, the &lt;code&gt;Query Executor&lt;/code&gt; might at times, under certain conditions, interrupt an ongoing query execution and re-evaluate a more optimal plan, especially if it notices that the initial plan isn't as efficient as anticipated.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Studio 3T Spotlight&lt;/strong&gt;: Visual Explain - A first look at visualizing your queries
&lt;/h2&gt;

&lt;p&gt;While understanding the inner workings of MongoDB is enlightening, there's a distinct difference between reading about it and seeing it in action. Enter Studio 3T's &lt;code&gt;Visual Explain&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Why Visualization Matters&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let's face it, while many of us can comprehend intricate details from textual explanations, there's something about visual representation that simplifies complexity. Much like how a roadmap can illustrate a journey better than a list of directions, &lt;code&gt;Visual Explain&lt;/code&gt; showcases the journey of your MongoDB query.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Getting Started with Visual Explain&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Studio 3T's &lt;code&gt;Visual Explain&lt;/code&gt; is as intuitive as it gets. When you create a query in Studio 3T, there's an option to visualize the query's execution plan. By selecting this, you're immediately presented with a visual breakdown of how MongoDB plans to, or has, executed your query.&lt;/p&gt;

&lt;p&gt;The visualization covers everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;Namespace&lt;/code&gt; and the path taken to reach the desired collection.&lt;/li&gt;
&lt;li&gt;The potential &lt;code&gt;Indexes&lt;/code&gt; that MongoDB considers, along with which ones are eventually used.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Query Selector&lt;/code&gt; and how the documents are filtered out based on the provided conditions.&lt;/li&gt;
&lt;li&gt;And finally, the &lt;code&gt;Projection&lt;/code&gt; which highlights the specific fields fetched from the documents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmnfdtp8p0kdplyz85fj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhmnfdtp8p0kdplyz85fj.png" alt="Visual Explain"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Benefits of Visual Explain&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;With &lt;code&gt;Visual Explain&lt;/code&gt;, you gain the ability to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Optimize Your Queries&lt;/strong&gt;: By observing the paths taken during query execution, you can identify bottlenecks and optimize your queries for better performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Understand Index Usage&lt;/strong&gt;: Visualize which indexes are being utilized and how they affect query performance. This can be invaluable when deciding on creating new indexes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Educational Value&lt;/strong&gt;: For those new to MongoDB, seeing the visualization can accelerate understanding, making the learning curve a bit gentler.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;Visual Explain&lt;/code&gt; doesn’t just clarify; it's a bridge to MongoDB's deeper workings.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;A Practical Use Case&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Imagine you operate an online computer store. Your database brims with product details stored in specific structured documents. These documents serve as the backbone for various operations, from inventory checks to customer queries. But lately, there's a hitch – performance has hit a snag. Let's dive into how &lt;code&gt;Visual Explain&lt;/code&gt; can be our detective and solution in one.&lt;/p&gt;

&lt;p&gt;Take a glance at a sample document from our collection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Premium Laptop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1299.99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"manufacturer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TechMaster Inc."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"San Francisco, USA"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"reviews"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LaptopLover123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Love it! Super fast."&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TechGuru22"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Great build, needs better battery."&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GamingEnthusiast"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"rating"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"comment"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Gaming champ! No lag."&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"laptop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"premium"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tech"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high performance"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, what's our mission? To retrieve laptops priced below $600. Here's how our query looks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"laptop"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"$lt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Studio 3T, &lt;code&gt;Visual Explain&lt;/code&gt; shows how MongoDB navigates this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhx7a6m7j2l078cy63y7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhx7a6m7j2l078cy63y7.png" alt="Visual Explain Before"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Pre-indexing landscape.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Indexing Decision&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Our visual feedback screams for efficiency. It takes almost half a second to find the laptops we need. The culprits? The database is performing a full scan over the "tags" and "price" fields, which is anything but quick. The way out? A compound index for these fields. However, a word of caution: while indexes supercharge read operations, they might add a tad delay to write processes. Striking the right balance is paramount.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Studio 3T’s Indexing Flow&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Launch Index Manager&lt;/strong&gt;: Expand your collection and double-click on &lt;code&gt;Indexes&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhenfzalw8qblaqbcs0f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhenfzalw8qblaqbcs0f.png" alt="Index Manager"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build the Compound Index&lt;/strong&gt;: Click &lt;code&gt;Add Index&lt;/code&gt;, choosing both "tags" and "price".&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fippv07i9e4tjqrm0wx5c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fippv07i9e4tjqrm0wx5c.png" alt="Compound Index Creation"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Review the Impact&lt;/strong&gt;: After going back to &lt;code&gt;Visual Explain&lt;/code&gt;, we could clearly see the improvement. The searches are now 4 times faster!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0vovqi8oo8hk0ky5ha0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe0vovqi8oo8hk0ky5ha0.png" alt="Post-Indexing Visualization"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;Visual Explain&lt;/code&gt;, we found that full scans were the issue. By adjusting our indexes, we made our searches quicker.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Beyond This Introduction&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;While we've touched upon the basics of MongoDB's query performance and indexing here, the depths and details, including how indexes function and the diverse types MongoDB offers, await in the upcoming articles of this series.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concluding Remarks: The Journey Forward
&lt;/h2&gt;

&lt;p&gt;As we come to the end of this introductory voyage into the heart of MongoDB's query performance, a few key thoughts emerge. Databases, as the silent orchestrators behind the symphony of digital interactions, bear an incredible weight of expectation. It's not just about storing data anymore – it's about doing so with agility, efficiency, and sophistication. MongoDB, with its non-relational structure and intelligent mechanics, rises to meet these challenges with aplomb.&lt;/p&gt;

&lt;p&gt;The tools and techniques we've discussed, especially Studio 3T's &lt;code&gt;Visual Explain&lt;/code&gt;, shed light on a world that often remains hidden beneath layers of code and abstracted complexity. They allow us, whether we're database novices or seasoned professionals, to visualize, understand, and optimize the intricate dance of query planning and execution.&lt;/p&gt;

&lt;p&gt;However, as deep as we've delved today, it's essential to remember that this is but the tip of the iceberg. Optimizing MongoDB's performance is a rich topic, layered with nuances and intricacies. Understanding and enhancing technology should always be seen as an ongoing journey, not a destination.&lt;/p&gt;

&lt;p&gt;That said, this is merely the opening act. In the upcoming installments of our series, "Enhancing MongoDB Query Performance", we'll explore more strategies, tools, and best practices. We'll dive deeper, ask tougher questions, and seek even more refined solutions to ensure that MongoDB doesn't just perform – it excels.&lt;/p&gt;

&lt;p&gt;Stay tuned and, as always, never stop questioning, learning, and optimizing. The digital age awaits, and we're just getting started.&lt;/p&gt;

</description>
      <category>mongodb</category>
      <category>database</category>
      <category>learning</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Announcing AnnaDB - next-gen NoSQL database</title>
      <dc:creator>Roman Right</dc:creator>
      <pubDate>Tue, 13 Sep 2022 10:20:53 +0000</pubDate>
      <link>https://forem.com/romanright/announcing-annadb-next-gen-nosql-database-3k3n</link>
      <guid>https://forem.com/romanright/announcing-annadb-next-gen-nosql-database-3k3n</guid>
      <description>&lt;p&gt;I'm excited to introduce &lt;a href="https://annadb.dev" rel="noopener noreferrer"&gt;AnnaDB&lt;/a&gt; - the next-generation developer-first NoSQL data store.&lt;/p&gt;

&lt;p&gt;I work with many small projects daily - proofs of concepts and experiments with new frameworks or patterns. For these purposes, I needed a database that works with flexible data structures, as I change it frequently during my experiments. And it must support relations out of the box, as this is a natural part of the structures' design - links to other objects. I tried a lot (if not all) databases, but nothing fit my requirements well. So, I decided to make my own then. This is how AnnaDB was born.&lt;/p&gt;

&lt;p&gt;AnnaDB is an in-memory data store with disk persistence. It is written with Rust, a memory-safe compilable language. AnnaDB is fast and safe enough to be and the main data storage, and the cache layer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flexible object structure - simple primitives and complicated nested containers could be stored in AnnaDB&lt;/li&gt;
&lt;li&gt;Relations - you can link any object to another, and AnnaDB will resolve this relation on finds, updates, and other operations.&lt;/li&gt;
&lt;li&gt;Transactions - out of the box&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Basics
&lt;/h2&gt;

&lt;p&gt;I want to start with the basic concepts and examples of the syntax here and continue with the usage example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Collections
&lt;/h3&gt;

&lt;p&gt;AnnaDB stores objects in collections. Collections are analogous to tables in SQL databases. &lt;/p&gt;

&lt;p&gt;Every object and sub-object (item of a vector or map) that was stored in AnnaDB has a link (id). This link consists of the collection name and unique uuid4 value. One object can contain links to objects from any collections - AnnaDB will fetch and process them on all the operations automatically without additional commands (joins or lookups)&lt;/p&gt;

&lt;h3&gt;
  
  
  TySON
&lt;/h3&gt;

&lt;p&gt;The AnnaDB query language uses the &lt;code&gt;TySON&lt;/code&gt; format. The main difference from other data formats is that each item has a value and prefix. The prefix can mark the data or query type (as it is used in AnnaDB) or any other useful for the parser information. This adds more flexibility to the data structure design - it is allowed to use as many custom data types as the developer needs.&lt;/p&gt;

&lt;p&gt;You can read more about the &lt;code&gt;TySON&lt;/code&gt; format &lt;a href="https://github.com/roman-right/tyson" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Types
&lt;/h3&gt;

&lt;p&gt;There are primitive and container data types in AnnaDB.&lt;/p&gt;

&lt;p&gt;Primitive data types are a set of basic types whose values can not be decoupled. In TySON, primitives are represented as &lt;code&gt;prefix|value|&lt;/code&gt; or &lt;code&gt;prefix&lt;/code&gt; only. Prefix in AnnaDB shows the data type. For example, the string &lt;code&gt;test&lt;/code&gt; will be represented as &lt;code&gt;s|test|&lt;/code&gt;, where &lt;code&gt;s&lt;/code&gt; - is a prefix that marks data as a string, and &lt;code&gt;test&lt;/code&gt; is the actual value.&lt;/p&gt;

&lt;p&gt;Container data types keep primitive and container objects using specific rules. There are only two container types in AnnaDB for now. Maps and vectors.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vectors are ordered sets of elements of any type. Example: &lt;code&gt;v[n|1|,n|2|,n|3|,]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Maps are associative arrays. Example: &lt;code&gt;m{ s|bar|: s|baz|,}&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More information about AnnaDB data types can be found in the &lt;a href="https://annadb.dev/documentation/data_types/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Query
&lt;/h3&gt;

&lt;p&gt;Query in AnnaDB is a pipeline of steps that should be applied in the order it was declared. The steps are wrapped into a vector with the prefix &lt;code&gt;q&lt;/code&gt; - query.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;collection&lt;/span&gt;|&lt;span class="value_primitive"&gt;test&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;q&lt;/span&gt;[
   &lt;span class="prefix_vector"&gt;find&lt;/span&gt;[
   ],
   &lt;span class="prefix_vector"&gt;sort&lt;/span&gt;[
      &lt;span class="prefix_modifier"&gt;asc&lt;/span&gt;(&lt;span class="prefix_primitive"&gt;value&lt;/span&gt;|&lt;span class="value_primitive"&gt;num&lt;/span&gt;|),
   ],
   &lt;span class="prefix_modifier"&gt;limit&lt;/span&gt;(&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;5&lt;/span&gt;|),
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If the pipeline has only one step, the &lt;code&gt;q&lt;/code&gt; vector is not needed.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;collection&lt;/span&gt;|&lt;span class="value_primitive"&gt;test&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;find&lt;/span&gt;[
   &lt;span class="prefix_map"&gt;gt&lt;/span&gt;{
      &lt;span class="prefix_primitive"&gt;value&lt;/span&gt;|&lt;span class="value_primitive"&gt;num&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;4&lt;/span&gt;|,
   },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;
  
  
  Server
&lt;/h3&gt;

&lt;p&gt;To run AnnaDB locally please type the next command in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--init&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 10001:10001 &lt;span class="nt"&gt;-t&lt;/span&gt; romanright/annadb:0.1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Client
&lt;/h3&gt;

&lt;p&gt;AnnaDB shell client is an interactive terminal application that connects to the DB instance, validates and handles queries. It fits well to play with query language or work with the data manually.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Froman-right%2FAnnaDB%2F0c9f00f53f21184fe166c5c70d417f0ed4bcf01b%2Fdocs%2Fbuild%2Fassets%2Fimg%2Fshell.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Froman-right%2FAnnaDB%2F0c9f00f53f21184fe166c5c70d417f0ed4bcf01b%2Fdocs%2Fbuild%2Fassets%2Fimg%2Fshell.png" alt="AnnaDB shell"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The client can be installed via &lt;code&gt;pip&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;annadb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;annadb &lt;span class="nt"&gt;--uri&lt;/span&gt; annadb://localhost:10001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage example
&lt;/h2&gt;

&lt;p&gt;You are prepared for the fun part of the article now. Let's play with AnnaDB!&lt;/p&gt;

&lt;p&gt;I'll create a database for the candy store to show the features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Insert primitive
&lt;/h3&gt;

&lt;p&gt;Let's start with categories. I'll represent categories as simple string objects. Let's insert the first one into the &lt;code&gt;categories&lt;/code&gt; collection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;collection&lt;/span&gt;|&lt;span class="value_primitive"&gt;categories&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;insert&lt;/span&gt;[
    &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;sweets&lt;/span&gt;|,
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;collection|categories|&lt;/code&gt; shows on which collection the query will be applied. In our case - &lt;code&gt;categories&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;insert[...]&lt;/code&gt; - is a query step. You can insert one or many objects using the &lt;code&gt;insert&lt;/code&gt; operation.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;s|sweets|&lt;/code&gt; - is the object to insert. In this case, it is a string primitive. Prefix &lt;code&gt;s&lt;/code&gt; means that it is a string, &lt;code&gt;|&lt;/code&gt; wrap the value of the primitive. Other primitive types could be found in the &lt;a href="https://annadb.dev/documentation/data_types/" rel="noopener noreferrer"&gt;Data Types section&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;result&lt;/span&gt;:&lt;span class="prefix_vector"&gt;ok&lt;/span&gt;[
    &lt;span class="prefix_map"&gt;response&lt;/span&gt;{
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;data&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;ids&lt;/span&gt;[
            &lt;span class="prefix_link"&gt;categories&lt;/span&gt;|&lt;span class="value_link"&gt;d2e9fecd-8b3d-429d-9a9b-34810120a221&lt;/span&gt;|,
        ],
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;meta&lt;/span&gt;|:&lt;span class="prefix_map"&gt;insert_meta&lt;/span&gt;{
            &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;count&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;1&lt;/span&gt;|,
        },
    },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If everything is ok, the result will have an &lt;code&gt;ok[...]&lt;/code&gt; vector with responses for all the transaction pipelines. Each response contains &lt;code&gt;data&lt;/code&gt; and &lt;code&gt;meta&lt;/code&gt; information. In our case, there is only one response with a vector of &lt;code&gt;ids&lt;/code&gt; in &lt;code&gt;data&lt;/code&gt; and a number of inserted objects in &lt;code&gt;meta&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Insert container
&lt;/h3&gt;

&lt;p&gt;Let's insert a more complicated object now - a chocolate bar. It will have fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;price&lt;/li&gt;
&lt;li&gt;category&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the category, I'll use the already created one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;collection&lt;/span&gt;|&lt;span class="value_primitive"&gt;products&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;insert&lt;/span&gt;[
    &lt;span class="prefix_map"&gt;m&lt;/span&gt;{
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;name&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;Tony's&lt;/span&gt;|,
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;price&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;5.95&lt;/span&gt;|,
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;category&lt;/span&gt;|:&lt;span class="prefix_link"&gt;categories&lt;/span&gt;|&lt;span class="value_link"&gt;d2e9fecd-8b3d-429d-9a9b-34810120a221&lt;/span&gt;|,
    },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The query is similar to the previous one, but the object is not a primitive but a map. The value of the &lt;code&gt;category&lt;/code&gt; field is a link that was received after the previous insert.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;result&lt;/span&gt;:&lt;span class="prefix_vector"&gt;ok&lt;/span&gt;[
    &lt;span class="prefix_map"&gt;response&lt;/span&gt;{
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;data&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;ids&lt;/span&gt;[
            &lt;span class="prefix_link"&gt;products&lt;/span&gt;|&lt;span class="value_link"&gt;17b12780-349c-4091-9bd2-7e08ad509ad0&lt;/span&gt;|,
        ],
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;meta&lt;/span&gt;|:&lt;span class="prefix_map"&gt;insert_meta&lt;/span&gt;{
            &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;count&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;1&lt;/span&gt;|,
        },
    },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The response is nearly the same as before - link in data and number of inserted objects in meta.&lt;/p&gt;

&lt;h3&gt;
  
  
  Get object
&lt;/h3&gt;

&lt;p&gt;Let's retrieve the information about this chocolate bar now. I'll use the &lt;code&gt;get&lt;/code&gt; operation for this, to the object by id&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;collection&lt;/span&gt;|&lt;span class="value_primitive"&gt;products&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;get&lt;/span&gt;[
    &lt;span class="prefix_link"&gt;products&lt;/span&gt;|&lt;span class="value_link"&gt;17b12780-349c-4091-9bd2-7e08ad509ad0&lt;/span&gt;|,
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This time I use the &lt;code&gt;get[...]&lt;/code&gt; query step. Using this step you can retrieve one or many objects using object links.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;result&lt;/span&gt;:&lt;span class="prefix_vector"&gt;ok&lt;/span&gt;[
    &lt;span class="prefix_map"&gt;response&lt;/span&gt;{
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;data&lt;/span&gt;|:&lt;span class="prefix_map"&gt;objects&lt;/span&gt;{
            &lt;span class="prefix_link"&gt;products&lt;/span&gt;|&lt;span class="value_link"&gt;17b12780-349c-4091-9bd2-7e08ad509ad0&lt;/span&gt;|:&lt;span class="prefix_map"&gt;m&lt;/span&gt;{
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;category&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;sweets&lt;/span&gt;|,
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;price&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;5.95&lt;/span&gt;|,
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;name&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;Tony's&lt;/span&gt;|,
            },
        },
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;meta&lt;/span&gt;|:&lt;span class="prefix_map"&gt;get_meta&lt;/span&gt;{
            &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;count&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;1&lt;/span&gt;|,
        },
    },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In the response here you can see the &lt;code&gt;objects{...}&lt;/code&gt; map, where keys are links to objects and values are objects. &lt;code&gt;objects{}&lt;/code&gt; map keeps the order - it will return objects in the same order as they were requested in the get step, or as they were sorted by the sort step.&lt;/p&gt;

&lt;p&gt;The category was fetched automatically and the value was returned.&lt;/p&gt;

&lt;p&gt;Let's insert another chocolate bar there to have more objects in the collection:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;collection&lt;/span&gt;|&lt;span class="value_primitive"&gt;products&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;insert&lt;/span&gt;[
    &lt;span class="prefix_map"&gt;m&lt;/span&gt;{
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;name&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;Mars&lt;/span&gt;|,
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;price&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;2&lt;/span&gt;|,
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;category&lt;/span&gt;|:&lt;span class="prefix_link"&gt;categories&lt;/span&gt;|&lt;span class="value_link"&gt;d2e9fecd-8b3d-429d-9a9b-34810120a221&lt;/span&gt;|,
    },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I use the same category id for this bar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modify primitive
&lt;/h3&gt;

&lt;p&gt;Let's modify the category to make it more accurate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;collection&lt;/span&gt;|&lt;span class="value_primitive"&gt;categories&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;q&lt;/span&gt;[
    &lt;span class="prefix_vector"&gt;get&lt;/span&gt;[
        &lt;span class="prefix_link"&gt;categories&lt;/span&gt;|&lt;span class="value_link"&gt;d2e9fecd-8b3d-429d-9a9b-34810120a221&lt;/span&gt;|,
    ],
    &lt;span class="prefix_vector"&gt;update&lt;/span&gt;[
        &lt;span class="prefix_map"&gt;set&lt;/span&gt;{
            &lt;span class="prefix_primitive"&gt;root&lt;/span&gt;:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;chocolate&lt;/span&gt;|,
        },
    ],
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The query here consists of 2 steps. &lt;code&gt;Get the object by link&lt;/code&gt; step and &lt;code&gt;modify this object&lt;/code&gt; step. The &lt;code&gt;update[...]&lt;/code&gt; operation is a vector of update operators. &lt;a href="https://annadb.dev/documentation/update/" rel="noopener noreferrer"&gt;Read more about the update&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;result&lt;/span&gt;:&lt;span class="prefix_vector"&gt;ok&lt;/span&gt;[
    &lt;span class="prefix_map"&gt;response&lt;/span&gt;{
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;data&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;ids&lt;/span&gt;[
            &lt;span class="prefix_link"&gt;categories&lt;/span&gt;|&lt;span class="value_link"&gt;d2e9fecd-8b3d-429d-9a9b-34810120a221&lt;/span&gt;|,
        ],
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;meta&lt;/span&gt;|:&lt;span class="prefix_map"&gt;update_meta&lt;/span&gt;{
            &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;count&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;1&lt;/span&gt;|,
        },
    },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The response of the update operation contains the ids of the updated objects as data and the number of the updated objects as meta.&lt;/p&gt;

&lt;p&gt;Let's take a look at how this affected the chocolate objects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;collection&lt;/span&gt;|&lt;span class="value_primitive"&gt;products&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;find&lt;/span&gt;[
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;To find objects, I use the &lt;code&gt;find[...]&lt;/code&gt; operation. It is a vector of find operators. If it is empty, all the collection objects will be returned.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;result&lt;/span&gt;:&lt;span class="prefix_vector"&gt;ok&lt;/span&gt;[
    &lt;span class="prefix_map"&gt;response&lt;/span&gt;{
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;data&lt;/span&gt;|:&lt;span class="prefix_map"&gt;objects&lt;/span&gt;{
            &lt;span class="prefix_link"&gt;products&lt;/span&gt;|&lt;span class="value_link"&gt;0b6ddf36-b8ba-487f-acd8-4dfee05d5177&lt;/span&gt;|:&lt;span class="prefix_map"&gt;m&lt;/span&gt;{
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;price&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;2&lt;/span&gt;|,
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;name&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;Mars&lt;/span&gt;|,
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;category&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;chocolate&lt;/span&gt;|,
            },
            &lt;span class="prefix_link"&gt;products&lt;/span&gt;|&lt;span class="value_link"&gt;17b12780-349c-4091-9bd2-7e08ad509ad0&lt;/span&gt;|:&lt;span class="prefix_map"&gt;m&lt;/span&gt;{
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;price&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;5.95&lt;/span&gt;|,
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;name&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;Tony's&lt;/span&gt;|,
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;category&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;chocolate&lt;/span&gt;|,
            },
        },
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;meta&lt;/span&gt;|:&lt;span class="prefix_map"&gt;find_meta&lt;/span&gt;{
            &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;count&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;2&lt;/span&gt;|,
        },
    },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The category was changed for both products, as the category object was linked with these objects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Modify container
&lt;/h3&gt;

&lt;p&gt;Now I'll increase the price of the bars, where it is less than 2&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;collection&lt;/span&gt;|&lt;span class="value_primitive"&gt;products&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;q&lt;/span&gt;[
    &lt;span class="prefix_vector"&gt;find&lt;/span&gt;[
        &lt;span class="prefix_map"&gt;lt&lt;/span&gt;{
            &lt;span class="prefix_primitive"&gt;value&lt;/span&gt;|&lt;span class="value_primitive"&gt;price&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;3&lt;/span&gt;|,
        },
    ],
    &lt;span class="prefix_vector"&gt;update&lt;/span&gt;[
        &lt;span class="prefix_map"&gt;inc&lt;/span&gt;{
            &lt;span class="prefix_primitive"&gt;value&lt;/span&gt;|&lt;span class="value_primitive"&gt;price&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;2&lt;/span&gt;|,
        },
    ],
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;find&lt;/code&gt; step can stay before the &lt;code&gt;update&lt;/code&gt; step as well. All the found objects will be updated. Read more about &lt;code&gt;find&lt;/code&gt; operation and operators &lt;a href="https://annadb.dev/documentation/find/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;result&lt;/span&gt;:&lt;span class="prefix_vector"&gt;ok&lt;/span&gt;[
    &lt;span class="prefix_map"&gt;response&lt;/span&gt;{
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;data&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;ids&lt;/span&gt;[
            &lt;span class="prefix_link"&gt;products&lt;/span&gt;|&lt;span class="value_link"&gt;0b6ddf36-b8ba-487f-acd8-4dfee05d5177&lt;/span&gt;|,
        ],
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;meta&lt;/span&gt;|:&lt;span class="prefix_map"&gt;update_meta&lt;/span&gt;{
            &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;count&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;1&lt;/span&gt;|,
        },
    },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The response is similar to the previous one.&lt;/p&gt;

&lt;p&gt;Here is how all the products look like after the update:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;result&lt;/span&gt;:&lt;span class="prefix_vector"&gt;ok&lt;/span&gt;[
    &lt;span class="prefix_map"&gt;response&lt;/span&gt;{
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;data&lt;/span&gt;|:&lt;span class="prefix_map"&gt;objects&lt;/span&gt;{
            &lt;span class="prefix_link"&gt;products&lt;/span&gt;|&lt;span class="value_link"&gt;0b6ddf36-b8ba-487f-acd8-4dfee05d5177&lt;/span&gt;|:&lt;span class="prefix_map"&gt;m&lt;/span&gt;{
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;category&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;chocolate&lt;/span&gt;|,
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;name&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;Mars&lt;/span&gt;|,
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;price&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;4&lt;/span&gt;|,
            },
            &lt;span class="prefix_link"&gt;products&lt;/span&gt;|&lt;span class="value_link"&gt;17b12780-349c-4091-9bd2-7e08ad509ad0&lt;/span&gt;|:&lt;span class="prefix_map"&gt;m&lt;/span&gt;{
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;name&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;Tony's&lt;/span&gt;|,
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;price&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;5.95&lt;/span&gt;|,
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;category&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;chocolate&lt;/span&gt;|,
            },
        },
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;meta&lt;/span&gt;|:&lt;span class="prefix_map"&gt;find_meta&lt;/span&gt;{
            &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;count&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;2&lt;/span&gt;|,
        },
    },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;
  
  
  Sort objects
&lt;/h3&gt;

&lt;p&gt;To sort objects, I'll use the &lt;code&gt;sort&lt;/code&gt; operation against the price field.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;collection&lt;/span&gt;|&lt;span class="value_primitive"&gt;products&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;q&lt;/span&gt;[
    &lt;span class="prefix_vector"&gt;find&lt;/span&gt;[
    ],
    &lt;span class="prefix_vector"&gt;sort&lt;/span&gt;[
        &lt;span class="prefix_modifier"&gt;asc&lt;/span&gt;(&lt;span class="prefix_primitive"&gt;value&lt;/span&gt;|&lt;span class="value_primitive"&gt;price&lt;/span&gt;|),
    ],
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;sort[...]&lt;/code&gt; operation is a vector of sort operators - &lt;code&gt;asc&lt;/code&gt; and &lt;code&gt;desc&lt;/code&gt;. Sort operators are modifiers that contain paths to the sorting value. The &lt;code&gt;sort&lt;/code&gt; operation is not an independent step, it can stay only after find-like operations that return objects. You can read more about sort &lt;a href="https://annadb.dev/documentation/update/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;result&lt;/span&gt;:&lt;span class="prefix_vector"&gt;ok&lt;/span&gt;[
    &lt;span class="prefix_map"&gt;response&lt;/span&gt;{
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;data&lt;/span&gt;|:&lt;span class="prefix_map"&gt;objects&lt;/span&gt;{
            &lt;span class="prefix_link"&gt;products&lt;/span&gt;|&lt;span class="value_link"&gt;0b6ddf36-b8ba-487f-acd8-4dfee05d5177&lt;/span&gt;|:&lt;span class="prefix_map"&gt;m&lt;/span&gt;{
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;name&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;Mars&lt;/span&gt;|,
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;price&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;4&lt;/span&gt;|,
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;category&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;chocolate&lt;/span&gt;|,
            },
            &lt;span class="prefix_link"&gt;products&lt;/span&gt;|&lt;span class="value_link"&gt;17b12780-349c-4091-9bd2-7e08ad509ad0&lt;/span&gt;|:&lt;span class="prefix_map"&gt;m&lt;/span&gt;{
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;category&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;chocolate&lt;/span&gt;|,
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;price&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;5.95&lt;/span&gt;|,
                &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;name&lt;/span&gt;|:&lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;Tony's&lt;/span&gt;|,
            },
        },
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;meta&lt;/span&gt;|:&lt;span class="prefix_map"&gt;find_meta&lt;/span&gt;{
            &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;count&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;2&lt;/span&gt;|,
        },
    },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Objects in the response are sorted by price now.&lt;/p&gt;

&lt;p&gt;It is useful to use &lt;code&gt;limit&lt;/code&gt; and &lt;code&gt;offset&lt;/code&gt; operations together with sort. You can read about them in the &lt;a href="https://annadb.dev/documentation/limit/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Delete objects
&lt;/h3&gt;

&lt;p&gt;After any find-like step, you can use the &lt;code&gt;delete&lt;/code&gt; operation to delete all the found objects. Or it can be used independently to delete the whole collection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;collection&lt;/span&gt;|&lt;span class="value_primitive"&gt;products&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;q&lt;/span&gt;[
    &lt;span class="prefix_vector"&gt;find&lt;/span&gt;[
        &lt;span class="prefix_map"&gt;gt&lt;/span&gt;{
            &lt;span class="prefix_primitive"&gt;value&lt;/span&gt;|&lt;span class="value_primitive"&gt;price&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;5&lt;/span&gt;|,
        },
    ],
    &lt;span class="prefix_primitive"&gt;delete&lt;/span&gt;,
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;delete&lt;/code&gt; operation is a primitive without value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Response&lt;/strong&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span class="prefix_primitive"&gt;result&lt;/span&gt;:&lt;span class="prefix_vector"&gt;ok&lt;/span&gt;[
    &lt;span class="prefix_map"&gt;response&lt;/span&gt;{
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;data&lt;/span&gt;|:&lt;span class="prefix_vector"&gt;ids&lt;/span&gt;[
            &lt;span class="prefix_link"&gt;products&lt;/span&gt;|&lt;span class="value_link"&gt;17b12780-349c-4091-9bd2-7e08ad509ad0&lt;/span&gt;|,
        ],
        &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;meta&lt;/span&gt;|:&lt;span class="prefix_map"&gt;update_meta&lt;/span&gt;{
            &lt;span class="prefix_string"&gt;s&lt;/span&gt;|&lt;span class="value_string"&gt;count&lt;/span&gt;|:&lt;span class="prefix_number"&gt;n&lt;/span&gt;|&lt;span class="value_number"&gt;1&lt;/span&gt;|,
        },
    },
];
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The response contains affected ids in &lt;code&gt;data&lt;/code&gt; and the number of deleted objects in &lt;code&gt;meta&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using from your app
&lt;/h2&gt;

&lt;p&gt;AnnaDB has a Python driver. It has an internal query builder - you don't need to learn AnnaDB query syntax to work with it. But it supports raw querying too.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pypi.org/project/annadb/" rel="noopener noreferrer"&gt;Link to the PyPI repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://annadb.dev/tutorial/python/" rel="noopener noreferrer"&gt;Python tutorial&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll add drivers for other languages soon. If you can help me with it, I'll be more than happy :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Plans
&lt;/h2&gt;

&lt;p&gt;This is the very early version of the database. It can already do things, and I use it in a few of my projects. But there are many features to work on yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Drivers
&lt;/h3&gt;

&lt;p&gt;I plan to add drivers to support the most popular languages, like &lt;code&gt;JS&lt;/code&gt;, &lt;code&gt;Rust&lt;/code&gt;, &lt;code&gt;Go&lt;/code&gt;, and others. If you can help with this - please get in touch with me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rights management
&lt;/h3&gt;

&lt;p&gt;This is probably the most important feature to implement. Authentication, authorizations, roles, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance increase
&lt;/h3&gt;

&lt;p&gt;There are many performance-related things to improve now. &lt;/p&gt;

&lt;h3&gt;
  
  
  Query features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Projections&lt;/li&gt;
&lt;li&gt;More find and update operators&lt;/li&gt;
&lt;li&gt;Developer experience improves&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Data Types
&lt;/h3&gt;

&lt;p&gt;I plan to add more data types like geo points and graph vertices to make AnnaDB more comfortable working with different data fields.&lt;/p&gt;

&lt;h3&gt;
  
  
  Managed service
&lt;/h3&gt;

&lt;p&gt;My big goal is to make a managed data store service. Hey, AWS, Google Cloud, MS Azure, I'm ready for collaborations! ;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Documentation - &lt;a href="https://annadb.dev" rel="noopener noreferrer"&gt;https://annadb.dev&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub Repo - &lt;a href="https://github.com/Anna-Team/AnnaDB" rel="noopener noreferrer"&gt;https://github.com/Anna-Team/AnnaDB&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Python Driver - &lt;a href="https://pypi.org/project/annadb/" rel="noopener noreferrer"&gt;https://pypi.org/project/annadb/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;My Twitter - &lt;a href="https://twitter.com/roman_the_right" rel="noopener noreferrer"&gt;https://twitter.com/roman_the_right&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;If you face any bug or weird behavior, please, let me know.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>database</category>
      <category>programming</category>
      <category>opensource</category>
      <category>rust</category>
    </item>
    <item>
      <title>Extend 3rd party classes. Rust's Implementations pattern in Python.</title>
      <dc:creator>Roman Right</dc:creator>
      <pubDate>Mon, 17 Jan 2022 12:50:31 +0000</pubDate>
      <link>https://forem.com/romanright/extend-3rd-party-classes-rusts-implementations-pattern-in-python-3hn8</link>
      <guid>https://forem.com/romanright/extend-3rd-party-classes-rusts-implementations-pattern-in-python-3hn8</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;There is a pattern called &lt;code&gt;Implementations&lt;/code&gt; in the Rust language. Using it you create methods and interfaces for the structures.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;odd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;is_strictly_positive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I decided to make the same but for Python. Meet &lt;a href="https://github.com/roman-right/impler"&gt;Impler&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The basic syntax
&lt;/h2&gt;

&lt;p&gt;You can extend any class with your own methods or even interface (class) using the &lt;code&gt;@impl&lt;/code&gt; decorator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;impler&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;impl&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;


&lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;impl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;distance_from_zero&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;distance_from_zero&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="c1"&gt;# 5.0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same way you can implement class or static methods&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;impl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;staticmethod&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;point1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;point2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;point2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;# 5.0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can implement the whole interface also.&lt;/p&gt;

&lt;p&gt;Here is an example of the base interface&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseFileInterface&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how you can implement this interface for Pydantic &lt;code&gt;BaseModel&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;impler&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;impl&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;


&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;impl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;as_parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ModelFileInterface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseFileInterface&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nb"&gt;classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the &lt;code&gt;as_parent&lt;/code&gt; parameter is &lt;code&gt;True&lt;/code&gt; the implementation will be injected into the list of the target class parents.&lt;/p&gt;

&lt;p&gt;Then you can check if the class or object implements the interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;issubclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BaseFileInterfase&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;# True
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real world use-case
&lt;/h2&gt;

&lt;p&gt;There is a csv file with data of some products:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+----+-----------+--------------+----------------+
|    | name      | created at   |   expire after |
|----+-----------+--------------+----------------|
|  0 | milk 3.5% | 2022-01-15   |              7 |
|  1 | sausage   | 2021-12-10   |             60 |
|  2 | yogurt    | 2021-12-01   |             20 |
+----+-----------+--------------+----------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I need to display if the product was expired already using pandas&lt;/p&gt;

&lt;p&gt;For this, I need to convert dates to the number of passed days. It would be great if DataFrame would have this method. Let's add it there.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;impler&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;impl&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pandas&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;DataFrame&lt;/span&gt;


&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;impl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;to_age&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Y"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"now"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timedelta64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;


&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"products.csv"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;to_age&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;"created at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"age in days"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s"&gt;"D"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"expired"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"expire after"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"age in days"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+----+-----------+--------------+----------------+---------------+-----------+
|    | name      | created at   |   expire after |   age in days | expired   |
|----+-----------+--------------+----------------+---------------+-----------|
|  0 | milk 3.5% | 2022-01-15   |              7 |             2 | False     |
|  1 | sausage   | 2021-12-10   |             60 |            38 | False     |
|  2 | yogurt    | 2021-12-01   |             20 |            47 | True      |
+----+-----------+--------------+----------------+---------------+-----------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the &lt;code&gt;to_age&lt;/code&gt; method returns self. It means this can be used in pandas methods chain, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;age_gt_10&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"products.csv"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
    &lt;span class="n"&gt;to_age&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;"created at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s"&gt;"D"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"age &amp;gt; 10"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age_gt_10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You probably noticed that the lib logo is a warning sign:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5qVK-Agd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/roman-right/impler/main/assets/logo.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5qVK-Agd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://raw.githubusercontent.com/roman-right/impler/main/assets/logo.svg" alt="Impler" width="384" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I want to warn you here too. Please, be careful - this lib patches classes.&lt;/p&gt;

&lt;p&gt;There are many scenarios where this tool could be used. I'd say it is good for extending 3rd party classes in research or experiment projects. It can be used in web services too but should be well tested.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;GH Project: &lt;a href="https://github.com/roman-right/impler"&gt;https://github.com/roman-right/impler&lt;/a&gt;&lt;br&gt;
PyPi: &lt;a href="https://pypi.org/project/impler/"&gt;https://pypi.org/project/impler/&lt;/a&gt;&lt;br&gt;
API Doc: &lt;a href="https://github.com/roman-right/impler/blob/main/docs/api.md"&gt;https://github.com/roman-right/impler/blob/main/docs/api.md&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>rust</category>
      <category>pattern</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Announcing Beanie ODM 1.8 - Relations, Cache, Actions and more!🎉🚀</title>
      <dc:creator>Roman Right</dc:creator>
      <pubDate>Mon, 29 Nov 2021 13:16:11 +0000</pubDate>
      <link>https://forem.com/romanright/announcing-beanie-odm-18-relations-cache-actions-and-more-24ef</link>
      <guid>https://forem.com/romanright/announcing-beanie-odm-18-relations-cache-actions-and-more-24ef</guid>
      <description>&lt;p&gt;I'm happy to introduce to you the new version of Beanie and a lot of new features, that come with it.&lt;/p&gt;

&lt;p&gt;Here is the feature list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Relations&lt;/li&gt;
&lt;li&gt;Event-based actions&lt;/li&gt;
&lt;li&gt;Cache&lt;/li&gt;
&lt;li&gt;Revision&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Relations
&lt;/h2&gt;

&lt;p&gt;This feature is perhaps the most anticipated of all. It took some time, but finally, it is here. Relations.&lt;/p&gt;

&lt;p&gt;The document can contain links to other documents in their fields.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Only top-level fields are fully supported for now.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Direct link to the document:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;beanie&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Link&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Door&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;House&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;door&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Door&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# This is the link
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;List of the links:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;beanie&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Link&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
    &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;House&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;door&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Door&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;windows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Window&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;  &lt;span class="c1"&gt;# This is the list of the links
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other link patterns are not supported for now. If you need something more specific for your use-case, please leave an issue on the GitHub page - &lt;a href="https://github.com/roman-right/beanie"&gt;https://github.com/roman-right/beanie&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Write
&lt;/h3&gt;

&lt;p&gt;The next write methods support relations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;insert(...)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;replace(...)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;save(...)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To apply the writing method to the linked documents, you should set the respective &lt;code&gt;link_rule&lt;/code&gt; parameter&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;house&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;windows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;house&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"NEW NAME"&lt;/span&gt;

&lt;span class="c1"&gt;# The next call will insert a new window object 
# and replace the house instance with updated data
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;house&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link_rule&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;WriteRules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WRITE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# `insert` and `replace` methods will work the same way
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or Beanie can ignore internal links with the &lt;code&gt;link_rule&lt;/code&gt; parameter &lt;code&gt;WriteRules.DO_NOTHING&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;house&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;door&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;house&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"NEW NAME"&lt;/span&gt;

&lt;span class="c1"&gt;# The next call will just replace the house instance 
# with new data, but the linked door object will not be synced
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;house&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link_rule&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;WriteRules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DO_NOTHING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# `insert` and `save` methods will work the same way
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Fetch
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Prefetch
&lt;/h4&gt;

&lt;p&gt;You can fetch linked documents on the find query step, using the parameter &lt;code&gt;fetch_links&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;houses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;House&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;House&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;fetch_links&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the find methods supported:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;find&lt;/li&gt;
&lt;li&gt;find_one&lt;/li&gt;
&lt;li&gt;get&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beanie uses a single aggregation query under the hood to fetch all the linked documents. This operation is very effective.&lt;/p&gt;

&lt;h4&gt;
  
  
  On-demand fetch
&lt;/h4&gt;

&lt;p&gt;If you don't use prefetching, linked documents will be presented as objects of the &lt;code&gt;Link&lt;/code&gt; class. You can fetch them manually then.&lt;br&gt;
To fetch all the linked documents you can use the &lt;code&gt;fetch_all_links&lt;/code&gt; method&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;house&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetch_all_links&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will fetch all the linked documents and replace &lt;code&gt;Link&lt;/code&gt; objects with them.&lt;/p&gt;

&lt;p&gt;Or you can fetch a single field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;house&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetch_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;House&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;door&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will fetch the Door object and put it in the &lt;code&gt;door&lt;/code&gt; field of the &lt;code&gt;house&lt;/code&gt; object.&lt;/p&gt;

&lt;h3&gt;
  
  
  Delete
&lt;/h3&gt;

&lt;p&gt;Delete method works the same way as write operations, but it uses other rules:&lt;/p&gt;

&lt;p&gt;To delete all the links on the document deletion you should use the &lt;code&gt;DeleteRules.DELETE_LINKS&lt;/code&gt; value for the &lt;code&gt;link_rule&lt;/code&gt; parameter&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;house&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link_rule&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DeleteRules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DELETE_LINKS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To keep linked documents you can use the &lt;code&gt;DO_NOTHING&lt;/code&gt; rule&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;house&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link_rule&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;DeleteRules&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DO_NOTHING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Event-based actions
&lt;/h2&gt;

&lt;p&gt;You can register methods as pre- or post- actions for document events like &lt;code&gt;insert&lt;/code&gt;, &lt;code&gt;replace&lt;/code&gt; and etc.&lt;/p&gt;

&lt;p&gt;Currently supported events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Insert&lt;/li&gt;
&lt;li&gt;Replace&lt;/li&gt;
&lt;li&gt;SaveChanges&lt;/li&gt;
&lt;li&gt;ValidateOnSave&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To register an action you can use &lt;code&gt;@before_event&lt;/code&gt; and &lt;code&gt;@after_event&lt;/code&gt; decorators respectively.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;beanie&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Insert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Replace&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;before_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Insert&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;capitalize_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;after_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;num_change&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is possible to register action for a list of events:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;beanie&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Insert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Replace&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;before_event&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;Insert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;capitalize_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will capitalize the &lt;code&gt;name&lt;/code&gt; field value before each document insert and replace&lt;/p&gt;

&lt;p&gt;And sync and async methods could work as actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;beanie&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Insert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Replace&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;after_event&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;Insert&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Cache
&lt;/h2&gt;

&lt;p&gt;All the query results could be locally cached.&lt;/p&gt;

&lt;p&gt;This feature must be turned on in the &lt;code&gt;Settings&lt;/code&gt; inner class explicitly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;use_cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Beanie uses LRU cache with expiration time. You can set &lt;code&gt;capacity&lt;/code&gt; (the maximum number of the cached queries) and expiration time in the &lt;code&gt;Settings&lt;/code&gt; inner class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;use_cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="n"&gt;cache_expiration_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;cache_capacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any query will be cached for this document class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# on the first call it will go to the database
&lt;/span&gt;&lt;span class="n"&gt;samples&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# on the second - it will use cache instead
&lt;/span&gt;&lt;span class="n"&gt;samples&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# if the expiration time was reached 
# it will go to the database again
&lt;/span&gt;&lt;span class="n"&gt;samples&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Revision
&lt;/h2&gt;

&lt;p&gt;This feature helps with concurrent operations. &lt;/p&gt;

&lt;p&gt;It stores &lt;code&gt;revision_id&lt;/code&gt; together with the document and changes it on each document update. If the application with the old local copy of the document will try to change it, an exception will be raised. Only when the local copy will be synced with the database, the application will be allowed to change the data. It helps to avoid losses of data.&lt;/p&gt;

&lt;p&gt;This feature must be turned on in the &lt;code&gt;Settings&lt;/code&gt; inner class explicitly too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;use_revision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any changing operation will check if the local copy of the document has the actual &lt;code&gt;revision_id&lt;/code&gt; value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"TestName"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;

&lt;span class="c1"&gt;# If a concurrent process already changed the doc, 
# the next operation will raise an error
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to ignore revision and apply all the changes even if the local copy is outdated, you can use the parameter &lt;code&gt;ignore_revision&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ignore_revision&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Other
&lt;/h2&gt;

&lt;p&gt;There is a bunch of smaller features, presented in this release. I would like to mention a couple of them here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Save changes
&lt;/h3&gt;

&lt;p&gt;Beanie can keep the document state, that synced with the database, to find local changes and save only them.&lt;/p&gt;

&lt;p&gt;This feature must be turned on in the &lt;code&gt;Settings&lt;/code&gt; inner class explicitly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;use_state_management&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To save only changed values the &lt;code&gt;save_changes()&lt;/code&gt; method should be used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Test"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save_changes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;save_changes()&lt;/code&gt; method can be used only with already inserted documents.&lt;/p&gt;

&lt;h3&gt;
  
  
  On save validation
&lt;/h3&gt;

&lt;p&gt;Pydantic has very useful config to validate values on assignment - &lt;code&gt;validate_assignment = True&lt;/code&gt;. But unfortunately, this is a heavy operation and doesn't fit some use cases.&lt;/p&gt;

&lt;p&gt;You can validate all the values before saving the document (insert, replace, save, save_changes) with beanie config &lt;code&gt;validate_on_save&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;This feature must be turned on in the &lt;code&gt;Settings&lt;/code&gt; inner class explicitly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;validate_on_save&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If any field has a wrong value, it will raise an error on write operations (insert, replace, save, save_changes)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Test"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"wrong value type"&lt;/span&gt;

&lt;span class="c1"&gt;# Next call will raise an error
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Thank you for reading. I hope you'll find these features useful.&lt;/p&gt;

&lt;p&gt;If you would like to help with development - there are some issues at the GitHub page of the project - &lt;a href="https://github.com/roman-right/beanie"&gt;https://github.com/roman-right/beanie&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/roman-right/beanie"&gt;Beanie Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://roman-right.github.io/beanie/"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://discord.gg/ZTTnM7rMaz"&gt;Discord Server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>mongodb</category>
      <category>async</category>
      <category>beanie</category>
    </item>
    <item>
      <title>Announcing Beanie 1.0 - MongoDB ODM with Query Builder🚀🎉</title>
      <dc:creator>Roman Right</dc:creator>
      <pubDate>Tue, 11 May 2021 07:59:59 +0000</pubDate>
      <link>https://forem.com/romanright/announcing-beanie-1-0-mongodb-odm-with-query-builder-4mbl</link>
      <guid>https://forem.com/romanright/announcing-beanie-1-0-mongodb-odm-with-query-builder-4mbl</guid>
      <description>&lt;p&gt;&lt;strong&gt;WARNING!!&lt;/strong&gt;&lt;br&gt;
This article is outdated. &lt;br&gt;
Please, follow the current documentation of Beanie to use actual features and patterns.&lt;br&gt;
Link to the doc - &lt;a href="https://roman-right.github.io/beanie/"&gt;https://roman-right.github.io/beanie/&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;I'm happy to introduce to you &lt;a href="https://github.com/roman-right/beanie"&gt;Beanie 1.0.0&lt;/a&gt; - Python ODM (Object Document Mapper) for MongoDB!&lt;/p&gt;

&lt;p&gt;Two months ago I published the very first Beanie release. You can find the article about it by the &lt;a href="https://dev.to/romanright/announcing-beanie-mongodb-odm-56e"&gt;link&lt;/a&gt;. I demonstrated there, how simple it is, to make a CRUD service with FastAPI and Beanie.  &lt;/p&gt;

&lt;p&gt;Many features were added since then. Today I want to show the most interesting things, which came with this major version update.&lt;/p&gt;

&lt;p&gt;For this demo, I will use the &lt;code&gt;Product&lt;/code&gt; document model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;beanie&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Document&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Indexed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pymongo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DESCENDING&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;
    &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"products"&lt;/span&gt;
        &lt;span class="n"&gt;indexes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pymongo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pymongo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Beanie Document is an abstraction over Pydantic BaseModel. It helps to make documents flexible and structured at the same time.&lt;/p&gt;

&lt;p&gt;For this demo I set up indexes here in two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple with the &lt;code&gt;Indexed&lt;/code&gt; field&lt;/li&gt;
&lt;li&gt;More complex with the &lt;code&gt;Collection&lt;/code&gt; inner class&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More information about document setup could be found by &lt;a href="https://roman-right.github.io/beanie/tutorial/install/"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create documents
&lt;/h2&gt;

&lt;p&gt;Beanie provides and single document creation pattern and batch inserts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;chocolate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Chocolate"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# One
&lt;/span&gt;&lt;span class="n"&gt;caramel_and_nougat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Caramel and Nougat "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                             &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;3.05&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                             &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;chocolate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;caramel_and_nougat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Many
&lt;/span&gt;&lt;span class="n"&gt;peanut_bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Peanut Bar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                     &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                     &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;4.44&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                     &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;chocolate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;truffle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Chocolate Truffle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                  &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                  &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;chocolate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert_many&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;peanut_bar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;truffle&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Find queries
&lt;/h2&gt;

&lt;p&gt;Now you can use Python native comparison operators with the document class fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Chocolate"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;find()&lt;/code&gt; method will return the &lt;code&gt;FindMany&lt;/code&gt; query, which uses an async generator pattern, and data can be available via &lt;code&gt;async for&lt;/code&gt; loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Chocolate"&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To retrieve the list, I use &lt;code&gt;to_list()&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Chocolate"&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;FindMany&lt;/code&gt; queries provide also sort, skip, limit, and project methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductShortView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;


&lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Chocolate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mf"&gt;3.5&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ProductShortView&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python comparison operators don't cover all the cases. Beanie provides a list of find operators, which could be used instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;beanie.operators&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt;

&lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Chocolate"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The whole list of the find operators can be found &lt;a href="https://roman-right.github.io/beanie/api/operators/find/"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use native PyMongo syntax for fine-tuning here too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"gte"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}}).&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need to find a single document, you can use the &lt;code&gt;find_one&lt;/code&gt; method instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Peanut Bar"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The detailed tutorial about finding the documents can be found by &lt;a href="https://roman-right.github.io/beanie/tutorial/find/"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Update
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;update()&lt;/code&gt; method allows updating documents using search criteria of the &lt;code&gt;FindMany&lt;/code&gt; and &lt;code&gt;FindOne&lt;/code&gt; queries.&lt;/p&gt;

&lt;p&gt;You can do it, using update operators:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;beanie.operators&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Inc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Set&lt;/span&gt;

&lt;span class="c1"&gt;# Many
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Peanut Bar"&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;

&lt;span class="c1"&gt;# One
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Chocolate Truffle"&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;

&lt;span class="c1"&gt;# or
&lt;/span&gt;
&lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Peanut Bar"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Inc&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The list of the update operators can be found by &lt;a href="https://roman-right.github.io/beanie/api/operators/update/"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Native PyMongo syntax is also supported for this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;"$set"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a list of preset update operations, which could be used as methods. Increment, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Chocolate"&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To update all the documents without the find query you can skip the &lt;code&gt;find&lt;/code&gt; step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Aggregations
&lt;/h2&gt;

&lt;p&gt;Aggregations, as updates, could be used over the whole collection or, using&lt;code&gt;FindMany&lt;/code&gt; searching criteria.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TotalCountView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alias&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;


&lt;span class="c1"&gt;# Over collection
&lt;/span&gt;
&lt;span class="n"&gt;total_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="s"&gt;"$group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"$category"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"$sum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"$num"&lt;/span&gt;&lt;span class="p"&gt;}}}],&lt;/span&gt;
    &lt;span class="n"&gt;projection_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;TotalCountView&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Subset
&lt;/span&gt;
&lt;span class="n"&gt;total_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="s"&gt;"$group"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"$category"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"$sum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"$num"&lt;/span&gt;&lt;span class="p"&gt;}}}],&lt;/span&gt;
    &lt;span class="n"&gt;projection_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;TotalCountView&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As for the update operations, there is a list of preset methods for the popular aggregations. For example, average:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;avg_choco_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Chocolate"&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;avg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://roman-right.github.io/beanie/api/interfaces/"&gt;Here&lt;/a&gt; you can find the doc with all the preset methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  Delete
&lt;/h2&gt;

&lt;p&gt;Delete operations support the same patterns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Many
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Chocolate"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# One
&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Peanut Bar"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Without fetching
&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_one&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Chocolate Truffle"&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In my first article, I said, that Beanie is a micro ODM. I'm removing the prefix &lt;code&gt;micro&lt;/code&gt; now. Beanie is a rich Python ODM for MongoDB with a lot of features, like query builder, projections, and migrations. It helps me to build services and applications a lot. I hope, it will help many other developers too.&lt;/p&gt;

&lt;p&gt;There is a list of interesting things, that I plan to add there. You are always welcome to participate in the development :-) Thank you very much for your time!&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/roman-right/beanie"&gt;Beanie Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://roman-right.github.io/beanie/"&gt;Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://discord.gg/ZTTnM7rMaz"&gt;Discord Server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>mongodb</category>
      <category>beanie</category>
    </item>
    <item>
      <title>Beanie Projections. Reducing network and database load.</title>
      <dc:creator>Roman Right</dc:creator>
      <pubDate>Wed, 21 Apr 2021 10:03:49 +0000</pubDate>
      <link>https://forem.com/romanright/beanie-projections-reducing-network-and-database-load-3bih</link>
      <guid>https://forem.com/romanright/beanie-projections-reducing-network-and-database-load-3bih</guid>
      <description>&lt;p&gt;&lt;strong&gt;WARNING!!&lt;/strong&gt;&lt;br&gt;
This article is outdated. &lt;br&gt;
Please, follow the current documentation of Beanie to use actual features and patterns.&lt;br&gt;
Link to the doc - &lt;a href="https://roman-right.github.io/beanie/"&gt;https://roman-right.github.io/beanie/&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Today I want to introduce to you a new &lt;a href="https://github.com/roman-right/beanie"&gt;Beanie&lt;/a&gt; feature. MongoDB projections are supported now. It helps to reduce database load and makes your services more efficient.&lt;/p&gt;

&lt;p&gt;How does it work? You can set up two document models for the same collection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A big one - for the regular operations&lt;/li&gt;
&lt;li&gt;A short one - for the case, when you need only a few fields&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Beanie is using MongoDB projections when it takes the data from the database. It means it is asking only the data, which was described in the model. Not filtering results but asking for limited data. This is reducing, and database load, and network load.&lt;/p&gt;

&lt;p&gt;I will show on small FastAPI service example:&lt;/p&gt;

&lt;p&gt;This is an ice cream store api. It has an Ice Cream entity. To create and get single ice cream I will use the long model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Nutrition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;energy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;fat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;protein&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;carbs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IceCream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;ingredients&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;per_100_gr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Nutrition&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ice-cream"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to return the list of the ice creams I'll use the short version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IceCreamShort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ice-cream"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the endpoints are neat as usual with FastAPI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# CREATE ICE CREAM
&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ice_cream_router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;IceCream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ice_cream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IceCream&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ice_cream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ice_cream&lt;/span&gt;

&lt;span class="c1"&gt;# GET SINGLE ICE CREAM
&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ice_cream_router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/{ice_cream_id}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;IceCream&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ice_cream_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;PydanticObjectId&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;ice_cream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;IceCream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ice_cream_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ice_cream&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="n"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;detail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Ice cream not found"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ice_cream&lt;/span&gt;

&lt;span class="c1"&gt;# GET LIST OF ALL THE AVAILABLE ICE CREAMS
&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ice_cream_router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;IceCreamShort&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_list&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;IceCreamShort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;IceCreamShort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's test. For the list endpoint it returns next:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"607fe424447d1f704c7b12ea"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ben &amp;amp; Jerry's Netflix &amp;amp; Chill'd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;7.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"summary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Peanut Butter Dairy Ice Cream with Sweet &amp;amp; Salty Pretzel Swirls &amp;amp; Brownie Pieces"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"607fe670447d1f704c7b12eb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Chip Happens"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"summary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A Cold Mess of Chocolate Ice Cream with Chocolatey Chips &amp;amp; Crunchy Potato Chip Swirls"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While for the single ice cream information it gives this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"607fe670447d1f704c7b12eb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Chip Happens"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"summary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A Cold Mess of Chocolate Ice Cream with Chocolatey Chips &amp;amp; Crunchy Potato Chip Swirls"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Sometimes “chip” happens and everything’s a mess, but we Nailed It! with this chip-filled limited batch. When smooth chocolate ice cream meets chocolatey chips &amp;amp; salty swirls, they pack a serious one-two crunch. The best part? There won’t be anything left to clean up."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ingredients"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"Cream (MILK) (26%)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"water"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"condensed skimmed MILK"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"sugar"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"vegetable oils (coconut, fully refined soybean, sunflower)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"glucose syrup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"potatoes"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"cocoa powder (1.5%)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"starch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"fat reduced cocoa powder (1%)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"free range EGG yolk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"vanilla extract"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"salt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"emulsifier (SOY lecithin)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"stabilisers (guar gum, carrageenan)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"MILK fat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"natural vanilla flavouring. Sugar, cocoa, vanilla: mass balance is used to match Fairtrade sourcing, total 20% F. F Visit info.fairtrade.net/sourcing"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"per_100_gr"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"energy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;277.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"fat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;17.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"protein"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"carbs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;27.0&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, it reduces database and network loads several times for the list view.&lt;/p&gt;

&lt;p&gt;The whole working project can be found by &lt;a href="https://github.com/roman-right/ice-cream-store"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/roman-right/beanie"&gt;Beanie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/roman-right/ice-cream-store"&gt;Demo Project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>mongodb</category>
      <category>beanie</category>
    </item>
    <item>
      <title>MongoDB indexes with Beanie</title>
      <dc:creator>Roman Right</dc:creator>
      <pubDate>Wed, 24 Mar 2021 15:20:45 +0000</pubDate>
      <link>https://forem.com/romanright/mongodb-indexes-with-beanie-43e8</link>
      <guid>https://forem.com/romanright/mongodb-indexes-with-beanie-43e8</guid>
      <description>&lt;p&gt;&lt;strong&gt;WARNING!!&lt;/strong&gt;&lt;br&gt;
This article is outdated. &lt;br&gt;
Please, follow the current documentation of Beanie to use actual features and patterns.&lt;br&gt;
Link to the doc - &lt;a href="https://roman-right.github.io/beanie/"&gt;https://roman-right.github.io/beanie/&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href="https://github.com/roman-right/beanie"&gt;Beanie&lt;/a&gt; - Python ODM (Object Document Mapper) for MongoDB.&lt;/p&gt;

&lt;p&gt;A few days ago Beanie &lt;strong&gt;0.3.0&lt;/strong&gt; was released. The most important feature of this version is Indexes support. In my &lt;a href="https://dev.to/romanright/announcing-beanie-mongodb-odm-56e"&gt;previous article&lt;/a&gt; I told about the general use-cases of this library. This time I would like to show in examples, what indexes are needed for and how to use them with Beanie.&lt;/p&gt;

&lt;p&gt;For this demo I will create a geo service to search interesting places around. Next functions will be provided:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upload map files to create the places. Files in &lt;code&gt;.KML&lt;/code&gt; format.&lt;/li&gt;
&lt;li&gt;Search for places by names and descriptions.&lt;/li&gt;
&lt;li&gt;Search for places around based on distance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I will use FastAPI to handle the requests. It is a very popular API framework now and fits perfectly with this demonstration.&lt;/p&gt;
&lt;h2&gt;
  
  
  Data Structure
&lt;/h2&gt;

&lt;p&gt;To store the places I will use Beanie &lt;code&gt;Document&lt;/code&gt; class. It is an abstraction over Pydantic &lt;code&gt;BaseModel&lt;/code&gt; that provides methods for working with MongoDB.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;enum&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Enum&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;beanie&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Document&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BaseModel&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GeoType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Point"&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GeoObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;GeoType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GeoType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;
    &lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;geo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;GeoObject&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"places"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Place&lt;/code&gt; data model contains fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; - the name of the place&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;description&lt;/code&gt; - a short description of the place&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;geo&lt;/code&gt; - geo information. As a datatype, I use &lt;code&gt;GeoObject&lt;/code&gt; here. It follows the data structure &lt;code&gt;GeoJSON Point&lt;/code&gt; of MongoDB. More information about this can be found &lt;a href="https://docs.mongodb.com/manual/reference/geojson/#geojson-point"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also use the inner class &lt;code&gt;Collection&lt;/code&gt;. It is optional. It helps to set up the MongoDB collection, where the documents are stored. For now, I'm just setting up the collection name there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Initialisation
&lt;/h2&gt;

&lt;p&gt;I'm creating the FastAPI app and init Beanie with the &lt;code&gt;Place&lt;/code&gt; document structure. No surprises here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ... some code skipped
&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;on_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"startup"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;app_init&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;motor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;motor_asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AsyncIOMotorClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;mongo_dsn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;init_beanie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;beanie_db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;document_models&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;include_router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;place_router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"places"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Upload the map file
&lt;/h2&gt;

&lt;p&gt;I will create an endpoint for uploading &lt;code&gt;.KML&lt;/code&gt; map files to the service. To parse the file I will use the &lt;code&gt;PyKML&lt;/code&gt; library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;place_router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/upload/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;StatusResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;places_from_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="p"&gt;(...)):&lt;/span&gt;
  &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromstring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;places&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Folder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;place_mark&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Placemark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;place_mark&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;

      &lt;span class="n"&gt;place&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;place_mark&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;geo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;GeoObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;place_mark&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;","&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;  &lt;span class="c1"&gt;# long-lat
&lt;/span&gt;      &lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;places&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;place&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert_many&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;places&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;StatusResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ResponseStatuses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;
  Click to see request details
  &lt;p&gt;POST &lt;code&gt;localhost:10001/v1/upload&lt;/code&gt; with file&lt;/p&gt;

&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;
    &lt;/span&gt;&lt;span&gt;"status"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"OK"&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;





&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;The endpoint receives the file in bytes format and provides it to the &lt;code&gt;PyKML&lt;/code&gt; parser. It extracts all the data, and I use it to create a list of &lt;code&gt;Place&lt;/code&gt; objects. Then I insert all the created objects together using the batch insert method &lt;code&gt;await Place.insert_many(places)&lt;/code&gt;. It is a very efficient way for inserting data when you have many objects.&lt;/p&gt;

&lt;p&gt;In this example, I'm using a map I found through the Google My Maps service. It is a nice map file with a collection of places in Belin. The file can be found in the demo project on &lt;a href="https://github.com/roman-right/beanie-index-demo/blob/main/beanie_index_demo/maps/Berlin%2C%20City%20Spy%20Map.kml"&gt;github&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Text search
&lt;/h2&gt;

&lt;p&gt;The next goal after uploading the map file is to make it able to search for places based on their names and descriptions. To do this I need to upgrade class &lt;code&gt;Place&lt;/code&gt; a little:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;geo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;GeoObject&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"places"&lt;/span&gt;
        &lt;span class="n"&gt;indexes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pymongo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pymongo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I added &lt;code&gt;TEXT&lt;/code&gt; index for the &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; fields. Now I can use MongoDB text search to find places:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_many&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;"$text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"$search"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"coffee"&lt;/span&gt;&lt;span class="p"&gt;}}).&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns a list of &lt;code&gt;Place&lt;/code&gt; objects, that have the string &lt;code&gt;coffee&lt;/code&gt; in the name or description field. So handy.&lt;/p&gt;

&lt;p&gt;Now I'm moving this to the endpoint and will append sorting and pagination there:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PlacesByPhraseInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;search_phrase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;


&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;place_router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/search/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;places_by_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;PlacesByPhraseInput&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find_many&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"$text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"$search"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;search_phrase&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
        &lt;span class="n"&gt;skip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;sort&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;
  Click to see request details
  &lt;p&gt;POST &lt;code&gt;localhost:10001/v1/search&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Input:&lt;br&gt;
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;
    &lt;/span&gt;&lt;span&gt;"search_phrase"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"coffee"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
    &lt;/span&gt;&lt;span&gt;"limit"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;
    &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"_id"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"605861b0a7bad9ea7250d130"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"name"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"19grams"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"description"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"Tiny hole in the wall serving Tres Cabezas locally roasted coffee &amp;amp; homemade cakes. Small space that fills up in winter then opens up onto the street in the summer. Perfect spot for a coffee refresh on the way to visit the Eastside gallery &amp;amp; Oberbaumbrucke.                                                                           Mon- Fri 08.oo- 18.oo Sat- Sun 10.oo- 18.oo"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"geo"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;
            &lt;/span&gt;&lt;span&gt;"type"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"Point"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
            &lt;/span&gt;&lt;span&gt;"coordinates"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;
                &lt;/span&gt;&lt;span&gt;13.4447623999999&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
                &lt;/span&gt;&lt;span&gt;52.4999605&lt;/span&gt;&lt;span&gt;
            &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;
    &lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;span&gt;
    &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"_id"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"605861b0a7bad9ea7250d131"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"name"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"19grams"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"description"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"After 15 years of serving house roasted coffee paired with exceptional homemade cakes. Loads of seating, in'n'out &amp;amp; a perfect pitstop from the weekend fleamarkets at Boxhagener Platz &amp;amp; RAW.                                                         Mon- 08.oo- 20.oo Sat- Sun 09.oo- 20.oo"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"geo"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;
            &lt;/span&gt;&lt;span&gt;"type"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"Point"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
            &lt;/span&gt;&lt;span&gt;"coordinates"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;
                &lt;/span&gt;&lt;span&gt;13.4687180999999&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
                &lt;/span&gt;&lt;span&gt;52.507127&lt;/span&gt;&lt;span&gt;
            &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;
    &lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;





&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;The endpoint returns the list according to the same search criteria, sorts it by name, and limits by &lt;code&gt;skip&lt;/code&gt; and &lt;code&gt;limit&lt;/code&gt; parameters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Geo search
&lt;/h2&gt;

&lt;p&gt;Now for the tastiest part - I'm going to implement a coordinate-based search. I will create an endpoint to lookup places around by the radius. To do this, I need to add one of the geospatial indexes to the &lt;code&gt;Places&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;geo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;GeoObject&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"places"&lt;/span&gt;
        &lt;span class="n"&gt;indexes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pymongo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pymongo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;  &lt;span class="c1"&gt;# TEXT indexes
&lt;/span&gt;            &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="s"&gt;"geo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pymongo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GEOSPHERE&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;  &lt;span class="c1"&gt;# GEO index
&lt;/span&gt;        &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I appended the &lt;code&gt;GEOSPHERE&lt;/code&gt; index to the &lt;code&gt;geo&lt;/code&gt; field. Now, to find the surrounded places I will use the &lt;code&gt;aggregate&lt;/code&gt; method. Suppose I am at Alexanderplatz with coordinates [13.413305998382263, 52.52203686798391] and I want to find the places in a distance of 1 kilometer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GeoObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;13.413305998382263&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;52.52203686798391&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;  &lt;span class="c1"&gt;# 1km
&lt;/span&gt;
&lt;span class="n"&gt;places&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"$geoNear"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s"&gt;"near"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="s"&gt;"distanceField"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"distance"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"maxDistance"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;item_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Place&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done. it returns a list of the &lt;code&gt;Place&lt;/code&gt; objects within 1 kilometer of me. Also, I used &lt;code&gt;"distanceField": "distance",&lt;/code&gt; parameter in the query. This means I can get the distances to each point I found. I'll update the output model a bit to achieve this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PlaceWithDistance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;


&lt;span class="n"&gt;places&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"$geoNear"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s"&gt;"near"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="s"&gt;"distanceField"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"distance"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"maxDistance"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;item_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;PlaceWithDistance&lt;/span&gt;  &lt;span class="c1"&gt;# Here I use new output model
&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now it also provides a distance together with other places information. I will wrap it to the endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PlacesAroundInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;place_router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/around/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PlaceWithDistance&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;places_by_radius&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;PlacesAroundInput&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;point&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GeoObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coordinates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Place&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s"&gt;"$geoNear"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s"&gt;"near"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                    &lt;span class="s"&gt;"distanceField"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"distance"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s"&gt;"maxDistance"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;item_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;PlaceWithDistance&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;to_list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;
  Click to see request details
  &lt;p&gt;POST &lt;code&gt;localhost:10001/v1/around&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Input:&lt;br&gt;
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;
    &lt;/span&gt;&lt;span&gt;"coordinates"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;13.413305998382263&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;52.52203686798391&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;span&gt;
    &lt;/span&gt;&lt;span&gt;"radius"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;2000&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;
    &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"_id"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"605861b0a7bad9ea7250d0ea"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"name"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"Serious Communist buildings"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"description"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;""&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"geo"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;
            &lt;/span&gt;&lt;span&gt;"type"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"Point"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
            &lt;/span&gt;&lt;span&gt;"coordinates"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;
                &lt;/span&gt;&lt;span&gt;13.418898&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
                &lt;/span&gt;&lt;span&gt;52.52335&lt;/span&gt;&lt;span&gt;
            &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"distance"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;405.9842140775255&lt;/span&gt;&lt;span&gt;
    &lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;span&gt;
    &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"_id"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"605861b0a7bad9ea7250d0f1"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"name"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"1.Berliner DDR Motorrad Museum"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"description"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;""&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"geo"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;
            &lt;/span&gt;&lt;span&gt;"type"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;"Point"&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
            &lt;/span&gt;&lt;span&gt;"coordinates"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;
                &lt;/span&gt;&lt;span&gt;13.4080193&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;
                &lt;/span&gt;&lt;span&gt;52.5238593&lt;/span&gt;&lt;span&gt;
            &lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;span&gt;
        &lt;/span&gt;&lt;span&gt;"distance"&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;411.55085454343913&lt;/span&gt;&lt;span&gt;
    &lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;span&gt;
    &lt;/span&gt;&lt;span&gt;...&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;





&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Done! &lt;/p&gt;

&lt;p&gt;I'm really impressed with the things MongoDB can do with geo indexes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I've demonstrated, what a useful and interesting thing indexes are and how comfortable it is to use them with Beanie. For sure there are many other use-cases and many other index types in MongoDB. And Beanie supports all of them and many other things. All the Beanie methods with examples can be found in the &lt;a href="https://roman-right.github.io/beanie/"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I've created &lt;a href="https://discord.gg/ZTTnM7rMaz"&gt;Beanie Discord server&lt;/a&gt; where you can ask your questions, tell me about bugs, share ideas or just chat. Everyone is welcome there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Demo - &lt;a href="https://github.com/roman-right/beanie-index-demo"&gt;https://github.com/roman-right/beanie-index-demo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Beanie project - &lt;a href="https://github.com/roman-right/beanie"&gt;https://github.com/roman-right/beanie&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Beanie Documentation - &lt;a href="https://roman-right.github.io/beanie/"&gt;https://roman-right.github.io/beanie/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Discord - &lt;a href="https://discord.gg/ZTTnM7rMaz"&gt;https://discord.gg/ZTTnM7rMaz&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>mongodb</category>
      <category>python</category>
      <category>beanie</category>
    </item>
  </channel>
</rss>
