#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. Это не фильтрует документы, созданные в течение определенного месяца.