doormen2014 2018-09-08 11:54
浏览 190
已采纳

如何通过包含JavaScript的mongo_go_driver运行汇总查询?

I'm using the mongo-go-driver (https://godoc.org/github.com/mongodb/mongo-go-driver/mongo) and I'm trying to do the equivalent of

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 can't figure out how to put the Javascript commands in using this method.

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

(In general, I dislike this method, anyway. I want to be able to design queries in Robo 3T and copy them to my code just like I do with MySQL Workbench and PHP)

This method yields an empty *bson.Array in 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'd really love it if there were a way to send Mongo a command as a string (like I was typing it into Robo 3T) and get a *mongo.Cursor back. Is there a better driver (that is still supported by someone) that I should use instead? Do I need to code my own?

Thanks!

  • 写回答

2条回答 默认 最新

  • doupaimo8288 2018-09-10 02:29
    关注

    I can't figure out how to put the Javascript commands in using this method.

    Although I understand this is not the preferred method for your use case, this is how to construct 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 also combined the two $match into a single pipeline stage instead, and then attach $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 value, it looks like you're storing date as string instead of a Date object. I would suggest to store dates as the proper Date objects for better index performance.

    Using ParseExtJSONArray DOES work, but, unlike Mongo Shell, you cannot include JS or unquoted aggregation stages / expression operators

    mongo shell provides some convienient methods/types i.e. ObjectID(), etc to construct MongoDB Extended JSON. The mongo shell is more than just a JavaScript shell.

    If your aim just to evaluate a JavaScript expression, you can utilise a JavaScript interpreter for Go (otto). A rough example would be:

    // 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 as mentioned above, there are some objects that will not be recognised by a normal JavaScript interpreter i.e. ObjectId()

    I want to be able to design queries in Robo 3T and copy them to my code just like I do with MySQL Workbench and PHP

    Although currently does not support Go, worth mentioning that MongoDB Compass has a feature to Export Query to Language. Current version (1.15) supports Java, Node, C# and Python3. Hopefully Go would be in the future.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥120 计算机网络的新校区组网设计
  • ¥20 完全没有学习过GAN,看了CSDN的一篇文章,里面有代码但是完全不知道如何操作
  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 海浪数据 南海地区海况数据,波浪数据
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?