Как запустить агрегатный запрос через mongo_go_driver, в котором есть javascript? - PullRequest
0 голосов
/ 08 сентября 2018

Я использую драйвер mongo-go (https://godoc.org/github.com/mongodb/mongo-go-driver/mongo) и пытаюсь сделать эквивалент

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()}} }
])

Я не могу понять, как поместить команды Javascript в этот метод.

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

(В общем, в любом случае, мне не нравится этот метод. Я хочу иметь возможность разрабатывать запросы в Robo 3T и копировать их в мой код, как я это делаю с MySQL Workbench и PHP)

Этот метод возвращает пустой * bson.Array в конвейере

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)

Мне бы очень понравилось, если бы был способ отправить Mongo команду в виде строки (как я набирал ее в Robo 3T) и получить * mongo.Cursor обратно. Есть ли лучший драйвер (который все еще поддерживается кем-то), который я должен использовать вместо этого? Нужно ли мне свой собственный код?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

Я не могу понять, как использовать команды Javascript с помощью этого метода.

Хотя я понимаю, что этот метод не является предпочтительным для вашего варианта использования, это способ построения конвейера агрегации как bson.D с использованием 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}},

Вы также можете вместо этого объединить два $match в одну стадию конвейера, а затем присоединить $project в конце. Например:

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: (новая дата (Date.now () - 1000 * 60 * 60 * 24)). ToISOString ()}}}

На основании значения $match выглядит, что вы сохраняете дату как string вместо Date объекта. Я бы предложил хранить даты как правильные Date объекты для лучшей производительности индекса.

Использование ParseExtJSONArray РАБОТАЕТ, но, в отличие от Mongo Shell, вы не можете включать JS или операторы агрегирования без кавычек / операторы выражений

Оболочка

mongo предоставляет несколько удобных методов / типов, т.е. ObjectID() и т. Д. Для построения MongoDB Extended JSON . Оболочка mongo - это больше, чем просто оболочка JavaScript.

Если ваша цель просто оценить выражение JavaScript, вы можете использовать интерпретатор JavaScript для Go (otto). Грубый пример будет:

// 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)

Обратите внимание, что, как упоминалось выше, есть некоторые объекты, которые не будут распознаваться обычным интерпретатором JavaScript, т.е. ObjectId ()

Я хочу иметь возможность разрабатывать запросы в Robo 3T и копировать их в мой код так же, как я делаю это с MySQL Workbench и PHP

Хотя в настоящее время не поддерживается Go, стоит упомянуть, что MongoDB Compass имеет функцию Экспорт запросов на язык . Текущая версия (1.15) поддерживает Java, Node, C # и Python3. Надеюсь, что Go будет в будущем.

0 голосов
/ 09 сентября 2018

Использование ParseExtJSONArray РАБОТАЕТ, но, в отличие от Mongo Shell, вы не можете включать JS или операторы агрегации / выражения без кавычек. Обратите внимание, что дата ISO для сравнения рассчитывается в голангах, а этапы агрегирования и операторы выражений агрегирования заключены в кавычки.

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)

С драйвером, о котором я спрашивал, это ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...