Фильтрация на основе даты внутри соответствующего объекта в массиве объектов

#mongodb #filter #aggregate

Вопрос:

У нас есть коллекция документов, которые выглядят следующим образом: введите описание изображения здесь

Временная шкала содержит различные события, произошедшие с определенным объектом. Я пытаюсь найти способ фильтрации объектов на основе даты внутри timeline объекта с status CREATED помощью .

Если я правильно это понимаю, я должен делать это с помощью агрегаций. Одна из возможных статей в этом направлении такова: https://docs.mongodb.com/manual/reference/operator/aggregation/first-array-element/

Я думаю об этом так: добавить этот соответствующий элемент временной шкалы в качестве дополнительного поля и сопоставить его.

Есть ли более простой (быстрый) способ достичь этого?

Результат, который я ищу, — это набор документов в течение определенного месяца, основанный на date поле в CREATED пункте под a timeline . Таким образом, в каждом документе есть объект timeline со статусом CREATED . У этого объекта есть date поле. Мне нужно отфильтровать коллекцию по этому признаку. Затем запустите набор агрегатов в отфильтрованной коллекции.

РЕДАКТИРОВАТЬ — Добавление дополнительных данных

Полный Документ

 {
    "_id": {
        "$oid": "55762fbf86c273233aebc101"
    },
    "from": {
        "nickname": "Savings",
        "type": "SYNAPSE-US",
        "id": "5574edcc86c27322ef865ea4",
        "user": {
            "legal_names": [
                "Some new name"
            ],
            "_id": "557387ed86c27318532fc09a"
        }
    },
    "extra": {
        "ip": "192.168.0.1",
        "supp_id": "1283764wqwsdd34wd13212",
        "webhook": "http://requestb.in/1acojwy1",
        "process_on": {
            "$date": "2015-06-10T00:13:51.263Z"
        },
        "note": "Deposit to bank account",
        "created_on": {
            "$date": "2015-06-09T00:13:51.263Z"
        },
        "other": {
            "skip_validation": false,
            "do_next": true
        },
        "latlon": "0,0",
        "same_day": false
    },
    "timeline": [
        {
            "date": {
                "$date": "2015-06-09T00:13:51.263Z"
            },
            "status": "CREATED",
            "note": "Transaction created",
            "status_id": "1"
        },
        {
            "status": "CANCELED",
            "note": "",
            "datetime": {
                "$date": "2015-06-25T00:37:00.515Z"
            },
            "status_id": "-1"
        },
        {
            "date": {
                "$date": "2015-07-07T07:16:44.756Z"
            },
            "status": "CREATED",
            "note": "Transaction unqueued",
            "status_id": "1"
        },
        {
            "date": {
                "$date": "2015-07-07T07:16:44.809Z"
            },
            "status": "PROCESSING-DEBIT",
            "note": "Transaction debit being processed.",
            "status_id": "2"
        },
        {
            "date": {
                "$date": "2015-07-07T07:16:44.853Z"
            },
            "status": "PROCESSING-CREDIT",
            "note": "Transaction credit being processed.",
            "status_id": "3"
        },
        {
            "date": {
                "$date": "2015-07-07T07:16:47.051Z"
            },
            "status": "SETTLED",
            "note": "Transaction credit has been made.",
            "status_id": "4"
        }
    ],
    "to": {
        "nickname": "ACH-US",
        "type": "ACH-US",
        "id": "5574d23b86c27354b2db471e",
        "user": {
            "legal_names": [
                "Some new name"
            ],
            "_id": "557387ed86c27318532fc09a"
        }
    },
    "amount": {
        "currency": "cUSD",
        "amount": 1010
    },
    "client": {
        "id": 844,
        "name": "Sankaet Pathak"
    },
    "fees": [
        {
            "note": "Synapse Facilitator Fee",
            "to": {
                "id": "559339aa86c273605ccd35df"
            },
            "fee": 25
        },
        {
            "note": "Facilitator Fee",
            "to": {
                "id": "559339aa86c273605ccd35df"
            },
            "fee": 100
        }
    ],
    "recent_status": {
        "date": {
            "$date": "2015-07-07T07:16:47.051Z"
        },
        "status": "SETTLED",
        "note": "Transaction credit has been made.",
        "status_id": "4"
    },
    "_v": 2
}
 

Комментарии:

1. Вы пытаетесь вернуть весь соответствующий документ? или вернуть совпадающие документы с удаленными несоответствующими записями временной шкалы?

2. @Joe Мне нужно будет запустить агрегаты и статистику по некоторым данным об этих объектах. Итак, мне понадобятся предметы.

3. можете ли вы предоставить данные в формате JSON и ожидаемый результат? также любая переменная, которую вы хотите использовать для проверки, у вас есть дата, которую вы хотите сравнить с датами на временной шкале?

4. @Takis_ Добавил более подробную информацию

5. В вашем примере показаны две записи для СОЗДАННЫХ — одна на 2015-06-09T00:13:51.263 Z и другая на 2015-07-07T07:16:44.756 Z. Запрос, пытающийся найти документы с временной шкалой «СОЗДАНО» в июле месяце, найдет этот документ, как и запрос за июнь. Ожидается ли это?

Ответ №1:

Таким образом, исходя из моего понимания, у вас может быть несколько CREATED записей на временной шкале, но если эта запись существует в течение месяца, о котором вы спрашиваете, документ действителен для извлечения. Вот агрегация, которая используется $elemMatch для поиска этих документов…

 Enterprise atlas-7aocnr-shard-0 [primary]> db.collection.find( { timeline: { $elemMatch: { status: "CREATED", $and: [ { date: { $gte: ISODate("2015-06-01") } }, { date: { $lt: ISODate("2015-07-01") } } ] } } } )
[
  {
    _id: ObjectId("55762fbf86c273233aebc101"),
    from: {
      nickname: 'Savings',
      type: 'SYNAPSE-US',
      id: '5574edcc86c27322ef865ea4',
      user: {
        legal_names: [ 'Some new name' ],
        _id: '557387ed86c27318532fc09a'
      }
    },
    extra: {
      ip: '192.168.0.1',
      supp_id: '1283764wqwsdd34wd13212',
      webhook: 'http://requestb.in/1acojwy1',
      process_on: 2015-06-10T00:13:51.263Z,
      note: 'Deposit to bank account',
      created_on: 2015-06-09T00:13:51.263Z,
      other: { skip_validation: false, do_next: true },
      latlon: '0,0',
      same_day: false
    },
    timeline: [
      {
        date: 2015-06-09T00:13:51.263Z,
        status: 'CREATED',
        note: 'Transaction created',
        status_id: '1'
      },
      {
        status: 'CANCELED',
        note: '',
        datetime: 2015-06-25T00:37:00.515Z,
        status_id: '-1'
      },
      {
        date: 2015-07-07T07:16:44.756Z,
        status: 'CREATED',
        note: 'Transaction unqueued',
        status_id: '1'
      },
      {
        date: 2015-07-07T07:16:44.809Z,
        status: 'PROCESSING-DEBIT',
        note: 'Transaction debit being processed.',
        status_id: '2'
      },
      {
        date: 2015-07-07T07:16:44.853Z,
        status: 'PROCESSING-CREDIT',
        note: 'Transaction credit being processed.',
        status_id: '3'
      },
      {
        date: 2015-07-07T07:16:47.051Z,
        status: 'SETTLED',
        note: 'Transaction credit has been made.',
        status_id: '4'
      }
    ],
    to: {
      nickname: 'ACH-US',
      type: 'ACH-US',
      id: '5574d23b86c27354b2db471e',
      user: {
        legal_names: [ 'Some new name' ],
        _id: '557387ed86c27318532fc09a'
      }
    },
    amount: { currency: 'cUSD', amount: 1010 },
    client: { id: 844, name: 'Sankaet Pathak' },
    fees: [
      {
        note: 'Synapse Facilitator Fee',
        to: { id: '559339aa86c273605ccd35df' },
        fee: 25
      },
      {
        note: 'Facilitator Fee',
        to: { id: '559339aa86c273605ccd35df' },
        fee: 100
      }
    ],
    recent_status: {
      date: 2015-07-07T07:16:47.051Z,
      status: 'SETTLED',
      note: 'Transaction credit has been made.',
      status_id: '4'
    },
    _v: 2
  }
]
 

Ответ №2:

Если вы хотите отфильтровать только «СОЗДАННЫЕ» объекты внутри массива временной шкалы , это правильный путь:

 mongos> db.z.aggregate([  
{ 
 $project:{ 
           timelines:{ 
                 $filter:{ 
                   input:"$timeline" , 
                      as:"item" , 
                    cond: { $eq:["$item.status","CREATED" ]  }
                         }
                    } 
           } 
 }    ]).pretty()

{
"_id" : {
    "oid" : "55762fbf86c273233aebc101"
},
"timelines" : [
    {
        "date" : {
            "$date" : "2015-06-09T00:13:51.263Z"
        },
        "status" : "CREATED",
        "note" : "Transaction created",
        "status_id" : "1"
    },
    {
        "date" : {
            "$date" : "2015-07-07T07:16:44.756Z"
        },
        "status" : "CREATED",
        "note" : "Transaction unqueued",
        "status_id" : "1"
    }
]
}
 mongos> 
 

Комментарии:

1. Это не фильтрует документы, созданные в течение определенного месяца.