Running an aggregate query in mongo_go_driver that includes javascript code: an easy guide

Currently, I am utilizing the mongo-go-driver () and attempting to achieve a similar action as below:

db.getCollection('mycollection').aggregate([
    { $lookup: {
        from: "anothercollection",
        localField: "_id",
        foreignField: "foreignID",
        as: "matched_docs"
    }},
    { $match: { "matched_docs": { $eq: [] } } },
    { $project: { "matched_docs": 0 } },
    { $match: {"dateTimeGMT":{$lt: (new Date(Date.now()-1000*60*60*24)).toISOString()}} }
])

I'm encountering difficulty in integrating the JavaScript commands using this approach.

pipeline := bson.NewArray(
    bson.VC.DocumentFromElements(
        bson.EC.SubDocumentFromElements( 
        //blah, blah, blah...
cursor, err := collection.Aggregate(ctx, pipeline)

(In general, I'm not fond of this technique. I desire the ability to develop queries in Robo 3T and easily transfer them into my code similar to how I perform with MySQL Workbench and PHP)

This method results in an empty *bson.Array within the pipeline

pipelineJSON := `[
    { $lookup: {
        from: "anothercollection",
        localField: "_id",
        foreignField: "interactionID",
        as: "matched_docs"
    }},
    { $match: { "matched_docs": { $eq: [] } } },
    { $project: { "matched_docs": 0 } },
    { $match: {"dateTimeGMT":{$lt: (new Date(Date.now()-1000*60*60*24)).toISOString()}} }
]`
pipeline, err = bson.ParseExtJSONArray(pipelineJSON)

I would greatly appreciate it if there was a way to transmit a MongoDB command as a string (like inputting it into Robo 3T) and receive a *mongo.Cursor in return. Is there a superior driver available (that is still actively supported by developers) that I should consider using instead? Or perhaps, do I need to develop my own?

Thank you!

Answer №1

I'm struggling to insert the Javascript commands using this particular approach.

While I acknowledge that this may not be the preferred method for your specific scenario, here is how you can build the aggregation pipeline as bson.D using mongo-go-driver v1.0:

pipeline := mongo.Pipeline{
    {{"$lookup", bson.D{
        {"from", "tour"}, 
        {"localField", "_id"}, 
        {"foreignField", "foreignID"}, 
        {"as", "matched_docs"},
    }}},
    {{"$match", bson.D{
        {"matched_docs", bson.D{
            {"$eq", bson.A{}}},
        }, 
    }}},
    {{"$project", bson.D{
        {"matched_docs", 0}, 
    }}},        
    {{"$match", bson.D{
        {"dateTimeGMT", bson.D{
            {"$lt", time.Now().AddDate(0, 0, -1).UTC().Format(time.RFC3339)},
            }, 
        },
    }}},  
}

{ $project: { "matched_docs": 0 } },

You can combine the two $match operations into a single pipeline stage and then add $project at the end. For example:

db.collection.aggregate([
    { "$lookup":{
        "from":"anothercollection",
        "localField":"_id",
        "foreignField":"foreignID",
        "as":"matched_docs"}
    }, 
    { "$match": { "matched_docs": { "$eq": [] }, 
                  "datetimegmt": { "$lt": (new Date(Date.now()-1000*60*60*24)).toISOString() } 
                } 
    }, 
    { "$project": { "matched_docs": 0 } }
]);

{ $match: {"dateTimeGMT":{$lt: (new Date(Date.now()-1000*60*60*24)).toISOString()}} }

Based on the $match condition, it seems like dates are stored as strings instead of Date objects. It's recommended to store dates as proper Date objects for better index performance.

ParseExtJSONArray does function properly, but you cannot include JS or unquoted aggregation stages/expression operators as in MongoDB Shell.

The mongo shell offers convenient methods/types like ObjectID() to create MongoDB Extended JSON. The mongo shell serves more than just a JavaScript environment.

If you simply need to evaluate a JavaScript expression, consider using a JavaScript interpreter for Go (otto). Here's a rough example:

// Note the unquoted fields, as JSON is JavaScript native.
raw := `[
    { "$lookup": {
        from: "anothercollection",
        localField: "_id",
        foreignField: "foreignID",
        as: "matched_docs"
    }},
    { $match: { "matched_docs": { $eq: [] },
                "dateTimeGMT":{$lt: (new Date(Date.now()-1000*60*60*24)).toISOString() }, 
              }
    },
    { $project: { "matched_docs": 0 } },
]`
vm := otto.New()
// Evaluate JS expression
jsvalue, err := vm.Eval(raw)

// Export to Go interface{}
output, err := jsvalue.Export()

// Convert interface{} to bson.Document bytes
bsonbytes, err := bson.Marshal(output)

// Convert bson.Document bytes to bson.Document
pipeline, err := bson.UnmarshalDocument(bsonbytes)

Note that some objects like ObjectId() won't be recognized by a standard JavaScript interpreter.

I wish to create queries in Robo 3T and transfer them to my code similar to MySQL Workbench with PHP.

Although currently lacking support for Go, it's worth noting that MongoDB Compass has a feature for Exporting Queries to Different Languages. The current version (1.15) supports Java, Node, C#, and Python3. Hopefully, Go will be included in the future.

Answer №2

When using ParseExtJSONArray, it functions properly. However, unlike Mongo Shell, you are unable to incorporate JS or unquoted aggregation stages/expression operators. It is important to note that the ISO date for comparison is calculated in golang and all aggregation stages and expression operators must be enclosed in quotes.

pipelineJSON := fmt.Sprintf(`[
    { "$lookup": {
        "from": "another_collection",
        "localField": "_id",
        "foreignField": "interactionID",
        "as": "matched_docs"
    }},
    { "$match": { "matched_docs": { "$eq": [] } } },
    { "$project": { "matched_docs": 0 } },
    { "$match": {"dateTimeGMT":{"$lt": "%s"}} }
]`, time.Now().AddDate(0, 0, -1).UTC().Format(time.RFC3339))
pipeline, err = bson.ParseExtJSONArray(pipelineJSON)

The driver I inquired about provides the solution to this issue.

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

Is it recommended to employ a switch statement in order to link CSS IDs with JavaScript variables?

function getVariableFromID(ID) { switch (ID) { case "GTA1": return GTA1; case "GTA2": return GTA2; case "GTA3": return GTA3; ... case "GTJ0": return GTJ0; } } In my code, I have implement ...

What is the best method for accessing a remote text file using JavaScript?

I have a text file located at \192.168.18.141\SnortLogs\alert_json.txt that I have shared using samba. I am able to access it through my Windows machine and now need to write JavaScript code to read the contents of this text file. ...

Transforming the shopping cart with redux-saga

Hey there! I've been working on implementing a shopping cart feature using redux-saga. The current code seems to be functioning properly, but I have some concerns about the way I'm handling the cart state. It looks like I might be mutating the ca ...

Tips for effectively testing an Angular directive

I'm having trouble testing an Angular directive due to encountering the following unexpected error: Error: Unexpected request: GET /api/players/info It seems that the issue may stem from references to my controller within the directive definition ob ...

Is it possible to verify if an event occurred within a specific hour, regardless of the date using Moment.js?

I am in the process of monitoring the usage patterns of a device and displaying users their usage trends by the hour. Essentially, I need to analyze times documents to determine if the device was active between specific hour intervals, such as 6pm to 7pm, ...

Using VueJS to Create a Range of Years from 1900 to Present Year

I'm currently developing a registration form using VueJS, wherein users need to input their date of birth. My challenge is in generating a list of years starting from 1900 up to the current year within a <select> element. Any suggestions on how ...

Bootstrap Modal inactive

Looking for someone with expertise in Bootstrap to help me out. I have a modal loading dynamic data from a MySQL database table, but the issue is that it appears disabled and I can't close it. I'm completely stuck and don't know how to fix i ...

Attempting to utilize a Python web scraping tool to extract content from a webpage that undergoes regular text updates

I must admit that I am a complete beginner who is feeling lost and unsure of what to do. My goal is to extract 4 pairs of numbers from a webpage using a web scraper. These numbers change when modified on a different page, but I'm unable to pull the d ...

Map markers for Google Places search not displaying properly

I am currently working on a demo to showcase the functionality of a future search feature. My goal is to query Google for information based on an address or area and then display the area bounds along with nearby places. To achieve this, I am utilizing too ...

Achieve this unique effect with titanium scroll view elements

I recently came across a fascinating feature in some applications. The feature involves an image with the letter A positioned in a specific area. As I scroll up, the label containing the letter A moves upward until it reaches the top of the screen. At tha ...

Set a class for the active menu item using jQuery based on the current window location

I have an HTML snippet here with a class called js-nav and a custom attribute named data-id. This data is crucial for determining the current sliding menu. <a class="nav-link js-nav" data-id="about" href="/#about">About</a> The approach I too ...

Deactivating the idle timer in React Native: A Step-by-Step Guide

Currently, I am working on an app that involves a timer using RN. However, I have noticed that after approximately 1 minute and 50 seconds, the device's screen starts to dim in preparation for sleep mode. ...

Accessing files for MongoDB cluster

My goal is to retrieve all the documents from a MongoDB cluster. Even though I have followed code examples from various online sources, I am encountering a minor issue. const MongoClient = require('mongodb'); const uri = "mongodb+srv://<user& ...

The JSON data rendered by Angular is causing disturbance

I am trying to create JSON from a multi-array in the following format: var qus ={ { "qus" :"what is your name?", "option1" : {"ans" : Alex, "cor:"false"}, "option2" : {"ans" : Hervy, "cor:"false"}, "option3" : {"ans" : Rico, "cor:"true"}, "option4" : {" ...

organize and identify a JSON data using sorting and matching techniques

Having a JSON structure as shown below: [ { "id": "1", "freq": "1", "value": "Tiruchengode", "label": "Tiruchengode" }, { "id": "2", "freq": "1", "value": "Coimbatore", "label": " ...

Set Divs in Absolute Position Relative to Each Other

I need to create a simple navigation system using <div> elements as individual pages. The goal is to have "next" and "back" buttons that allow users to switch between these pages with a smooth fade-in and fade-out effect, all powered by jQuery. Howev ...

Using Javascript or jQuery to Enhance the Appearance of Text on a Website

Is there a way to automatically apply styling to specific phrases on our website by searching for instances of those phrases? For example: <div> This is what you get from <span class="comp">Company Name</span>. We do all kin ...

Will refreshing just a specific component update the entire page or only that particular component that was altered?

As a newcomer to React, I am thoroughly enjoying the experience so far. However, I have a basic question that is currently unclear to me. Specifically, I am in the process of learning how to lift the state of a component, and I have a reproducible example ...

Utilizing a duo of jQuery event handlers to execute a common series of tasks

For this scenario, my goal is to make my if statement using .css function work on both .ready and .resize events, but I'm unsure how to merge them effectively. var windowsize = $(window).width(); $(window).ready(function() { windowsize = $(window). ...

The Minimax algorithm experiencing issues in Next.js

I recently wrote some code in Next.js, but unfortunately, it's not functioning as expected. Despite my best efforts and attempts at utilizing alpha beta pruning, the code still fails to work properly. The issue lies in the fact that it simply returns ...