Performing the $substr operation on each element within an array of strings in MongoDB

A custom aggregation has been created to search for values beginning with a specified query and prioritize exact matches in the results. The field tags is an array containing one or more strings.

results = await Post.aggregate([

    // Find all tags that start with the given query
    { $match: { 'tags': new RegExp("^" + query, 'i') } },

    { $addFields: {
        // Identify if there is an exact match of the query in any string value
        'exactMatch': { $eq: [ '$tags', query ] },

        // Check if the first 3 characters of any string value match the query
        'startsWith': { $eq: [ { $substr: [ '$tags', 0, 3 ] }, query ] },
    } },

    // Prioritize exact matches first
    { $sort: { 'exactMatch': -1, 'startsWith': -1 } },

    // Remove the added fields from results
    { $project: { 'exactMatch': 0, 'startsWith': 0 } }
])

This method works well with a single string in the tags field, but I am facing difficulties when using an array of strings.

The issue arises from this particular line of code:

// Check if the first 3 characters of any string value match the query
'startsWith': { $eq: [ { $substr: [ '$tags', 0, 3 ] }, query ] },

Since the tags field is an array, the $substr function encounters an error due to its inability to convert from BSON type array to String:

MongoServerError: PlanExecutor error during aggregation :: caused by :: can't convert from BSON type array to String

How can I modify this code to target individual values within the array instead of the array itself?

(Edit) Sample data, input & expected results

When considering the following data:

[
    {
        title: 'Post1',
        content: 'This is test post 1.',
        tags: [
            'post', '12345'
        ]
    },
    {
        title: 'Post2',
        content: 'This is test post 2.',
        tags: [
            'post', '789'
        ]
    },
    {
        title: 'Post3',
        content: 'This is test post 3.',
        tags: [
            'post', '123'
        ]
    }
]

And using an input query of "123", the expected results should be as follows:

[
    {
        title: 'Post3',
        content: 'This is test post 3.',
        tags: [
            'post', '123'
        ]
    },
    {
        title: 'Post1',
        content: 'This is test post 1.',
        tags: [
            'post', '12345'
        ]
    }
]

Answer №1

Revised your query.

To effectively handle the array of tags, utilize $filter to filter each element in the array, and then check if the resulting array is not empty.

results = await Post.aggregate([

    // Find all tags that start with the provided query
    { $match: { 'tags': new RegExp("^" + query, 'i') } },

    {
    $addFields: {
      // Add a field 'true' for exact matches of the query in string values
      "exactMatch": {
        $ne: [
          {
            $filter: {
              input: "$tags",
              cond: {
                $eq: [
                  "$$this",
                  query
                ]
              }
            }
          },
          []
        ]
      },
      // Add a field 'true' for first 3 characters matching the query in string values
      "startsWith": {
        $ne: [
          {
            $filter: {
              input: "$tags",
              cond: {
                $eq: [
                  {
                    $substr: [
                      "$$this",
                      0,
                      3
                    ]
                  },
                  query
                ]
              }
            }
          },
          []
        ]
      }
    }
  },

    // Prioritize exact matches first
    { $sort: { 'exactMatch': -1, 'startsWith': -1 } },

    // Remove the added fields from results
    { $project: { 'exactMatch': 0, 'startsWith': 0 } }
])

See Demo @ Mongo Playground

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Looking to enhance my current workaround for utilizing Google Spreadsheet's ImportRange feature

I recently joined this forum and have just started using Google Scripts. I don't have any prior experience with JavaScript or programming languages, but had to learn them when I decided to use Google Apps as the main platform for my small business. M ...

Reduce two array fields conditionally in a MongoDB aggregation pipeline

I've got a dataset that resembles the following: { "_id": 1, "user": "abc", "sentence": "I like to read books.", "nouns": [ "books" ], "verbs": [ "read" ] }, { "_id": 2, "user": "abc", "sentence": "Reading is my favorite h ...

Running commands in brunch

I'm a beginner when it comes to brunch, and I seem to be facing some issues with setting it up correctly. I am using the dead simple skeleton, and I have included a script (main.js) in the app > scripts directory. The script simply contains a conso ...

Transferring JSON data using $.post in Express/NodeJS

Below is the contents of my app.js file: var express = require('express'); var app = express(); var path = require('path'); var $ = require('jquery'); var nodemailer = require('nodemailer'); app.use('/static&a ...

The Angular single-page application is experiencing issues with the ngResource dependency and

When trying to use ngResource in Angular, I encountered an issue where adding the dependency caused blank pages to display. I have included the script reference, but it's still not functioning correctly. What steps should I take to resolve this? /*va ...

Extracting the text that is displayed on a specific element

I have a very simple question that I can't seem to find an answer for due to the lack of documentation on the javascript bindings of selenium-webdriver. While there is ample documentation for the java bindings, the same cannot be said for javascript. ...

Query MongoDB to filter documents based on the presence or absence of a specific field or its value

In MongoDB, there are certain records structured like this: model: Category {_id: id1, owner: owner1} {_id: id2, owner: owner1} {_id: id3, deleted: false, owner: owner1} {_id: id4, deleted: false, owner: owner2} {_id: id5, deleted: true, owner: owner1} {_i ...

What is the process for obtaining the outcome of an ajax request?

After the request is complete, I want to run specific code. I'm unsure if this is the correct approach. Can you provide guidance on this? Thank you! Handling Ajax Requests function sendRequest(url, data, type) { return $.ajax({ url: ur ...

What are the steps to resolve the CORS policy problem when making a GET request?

Can someone assist me in resolving the CORS policy issue I am facing? This problem occurs when I attempt to make a GET request to the applications endpoint, and it seems to only happen when accessing from http://localhost:8080/ - the request works fine in ...

How to verify if an object is empty in an AngularJS expression

I need to display either a Login or Logout button based on the value of a $rootScope variable. Currently, only the Logout button is showing up in the li tag below. I have specific actions that should occur after certain events: After Logging In:- $root ...

Encountered issue establishing connection to MongoDB within JBoss deployment

Encountered an issue while deploying a war file that connects to MongoDB on JBoss, resulting in the following error: Request { "address" => [("deployment" => "moc-public-api-1.0_SNAPSHOT.war")], "operation" => "deploy" } Response Intern ...

What could be causing this issue in the JavaScript code?

Can anyone explain why this code isn't functioning correctly? Although it prints "generating fish," nothing is being printed after that. function fish(x, y, degree, genes, Snumber) { this.x = x; this.y = y; this.d ...

Obtain a button located within a div using a JavaScript file

I am currently immersed in a MVC ASP .NET Project. Within my View folder resides the Dashoboard.cshtml file, which contains the following code: <div id="something"> <button type="button" class="btn btn-primary">Export To PDF</b ...

Display the MongoDB document _id in PHP

I'm currently creating a solution that involves the use of a mix of jQuery, PHP, and MongoDB. After running a PHP query that returns an array, I want to display the results using the print_r function on a web page. Everything is working well except fo ...

Error in React: Attempting to access the first index of an undefined property

I'm trying to develop a function that calculates the total of individual columns in a matrix of 12 rows and then creates a new array with those total values. However, I keep running into the following error: TypeError: Cannot read property '0&ap ...

How can I click on an element using either the href or span substring in Protractor?

Here are the details of the element I am trying to interact with using Protractor. <hsx-nav-menu-group hsx-html-element> == $0 <hsx-nav-menu-info> <i hsx-html-element hsx-icon> <svg> <use ...

The error message "TypeError: 'undefined' is not an object ('_this.props')" indicates that the property '_this

Having trouble solving this issue. Need assistance with evaluating 'this.props.speciesSelection.modalize' <BarcodeInput speciesSelection={this.props.speciesSelection} species={species[0]} barcode={{ manufacturerValue: ...

JQuery validation for phone number format 01x-xxxxxxxx

Currently, I am using jQuery Validate to validate the form. In order to validate the phone number field, I have implemented the following code: The phone number should be written in the format 01x-xxxxxxxx var phonereg = /^[0-9]{3}\-[0-9]{7}$/; H ...

Dealing with CORS policy challenge

I am encountering an issue with Access to XMLHttpRequest at 'http://demo.equalinfotech.com/Iadiva/images/product/1634623781ladiva_barbara_01.glb' from origin 'http://localhost:8100' being blocked by CORS policy due to the absence of the ...

Issue with BlobUrl not functioning properly when included as the source in an audio tag

I need help with playing an audio file on click. I tried to implement it but for some reason, it's not working as expected. The response from the server is in binary format, which I decoded using base64_decode(responseFromServer); On the frontend (Vu ...