Как проанализировать расширенную дату JSON в конвейере агрегации, используя ParseExtJSONArray() в mongo-go-driver

У меня есть коллекция с полем Дата:

{
    "_id" : ObjectId("5b92b359ddceef5b24502834"),
    "dateTimeGMT" : ISODate("2018-08-22T09:29:25.000Z"),
    yada, yada, yada
}

Я пытаюсь найти по дате на этапе агрегации $match с помощью функции ParseExtJSONArray mongo-go-driver. (Я знаю, как сделать это с *bson.Array напрямую. Я спрашиваю, чтобы я знал, как правильно сделать это с ParserExtJSONArray или если я столкнулся с ограничением.)

Я упростил этот пример и подтвердил, что он не соответствует приведенному выше документу.

pipeline, err := bson.ParseExtJSONArray(`[
    { "$match": { "dateTimeGMT.$date":"2018-08-22T09:29:25.000Z" } }
]`)
cursor, err := receivedFromResponseQueue.Aggregate(ctx, pipeline)

Следующее не работает в оболочке Монго. (Не удивительно, потому что он автоматически конвертируется в формат ISODate())

db.getCollection('received_from_response_queue').aggregate([
    { "$match": { "dateTimeGMT.$date":"2018-08-22T09:29:25.000Z" } }
])

Но это работает в оболочке Монго.

db.getCollection('received_from_response_queue').aggregate([
    { "$match": { "dateTimeGMT": ISODate("2018-08-22T09:29:25.000Z") } }
])

Но это возвращает пустой массив в "конвейере". (Потому что ParseExtJSONArray не обрабатывает JavaScript)

pipeline, err := bson.ParseExtJSONArray(`[
    { "$match": { "dateTimeGMT":ISODate("2018-08-22T09:29:25.000Z") } }
]`)

Поскольку затем он использует пустой массив, он перенастраивает все документы в коллекции. Интересно, что в документе, который мы пытаемся сопоставить, дата форматируется по-разному.

{
    "_id" : { "$oid" : "5b92b359ddceef5b24502834" },
    "dateTimeGMT" : { "$date" : "2018-08-22T05:29:25-04:00" },
    yada yada yada
}

Но это тоже не совпадает.

pipeline, err := bson.ParseExtJSONArray(`[
    { "$match": { "dateTimeGMT.$date":"2018-08-22T05:29:25-04:00" } }
]`)
cursor, err := receivedFromResponseQueue.Aggregate(ctx, pipeline)

И это не работает в оболочке Монго.

db.getCollection('received_from_response_queue').aggregate([
    { "$match": { "dateTimeGMT.$date":"2018-08-22T05:29:25-04:00" } }
])

Любое понимание?

1 ответ

Решение

Идея MongoDB Extended JSON заключается в том, чтобы представлять двоичные типы JSON ( BSON) в виде простого JSON.

Общий синтаксис должен представлять объект как один встроенный документ. Например, двоичный объект BSON представлен в виде документа {"$binary": "<binary data>"}, $ префикс в поле ключа указывает тип. То же самое относится к объекту даты BSON.

Метод bson.ParseExtJSONArray() ожидает, что расширенные типы JSON будут документами, а не выражением нотации MongoDB. Например, вместо ниже:

{ "$match": { "dateTimeGMT.$date":"2018-08-22T09:29:25.000Z" } }

Метод ожидает:

{ "$match": { "dateTimeGMT": {"$date":"2018-08-22T09:29:25.000Z" } } }

Вы также можете указать значение даты в Unix Epoch, например:

{ "$match": { "dateTimeGMT": {"$date": { "$numberLong": "1546300800"} } } }

Используя mongo-go-driver / bson, пример будет:

raw := `[ { "$match": {"dateTimeGMT": {"$date": {"$numberLong": "1530962624753" } } } } ]`
pipeline, err := bson.ParseExtJSONArray(raw)
cursor, err := collection.Aggregate(context.Background(), pipeline)

Дополнительное примечание: вы можете отлаживать ParseExtJSONArray() перед передачей полученного значения в агрегацию путем итерации по нему. Например:

toConvert := `[
   { "$lookup": {
        "from": "anotherCollection",
        "localField": "foreignKey",
        "foreignField": "_id",
        "as": "someField"
    }},
    { "$match": {"dateTimeGMT":{"$lt": {"$date": "2019-01-10T09:29:25.000Z" } } } }
]`
pipeline, err := bson.ParseExtJSONArray(toConvert)

it, err := bson.NewArrayIterator(pipeline)
for it.Next() {
    fmt.Println(it.Value().MutableDocument().ToExtJSON(true))
}

//Outputs : 
//   {"$lookup":{"from":"anotherCollection","localField":"foreignKey","foreignField":"_id","as":"someField"}}
//   {"$match":{"dateTimeGMT":{"$lt":{"$date":{"$numberLong":"1547112565000"}}}}}
//
Другие вопросы по тегам