Спасибо за образец данных. Мой ответ будет сырым решением MQL, а не решением мангуста, поэтому потребуется некоторый перевод.
Я смог вставить два документа, основанных на ваших комментариях в вашем посте. Мне пришлось изменить идентификатор объекта одного из двух образцов документов, потому что ваши образцы имели одинаковое значение первичного ключа и создавали исключение дубликата ключа.
Вставьте Примеры Данных
db.CallerTraces.insert(
{
"_id": ObjectId("6175e7ecc62cff004462d4a6"),
"traces": [
[
ObjectId("6175e7ecc62cff004462d4a4")
]
],
"caller_address": "0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990"
})
db.CallerTraces.insert(
{
"_id": ObjectId("6175e7ecc62cff004462d4a7"),
"traces": [
[
ObjectId("6175e7ecc62cff004462d4a4"),
ObjectId("6175e7ecc62cff004462d4a4")
],
[
ObjectId("6175e7ecc62cff004462d4a4")
]
],
"caller_address": "0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990"
})
Если я хочу найти записи, содержащие более 0 элементов в массиве traces
Я могу выдать следующее:
Найдите более нуля следов
db.CallerTraces.find({ $expr: { $gt: [ { $size: "$traces" }, 0 ] } })
Это возвращает следующее:
Enterprise replSet [primary] barrydb> db.CallerTraces.find({ $expr: { $gt: [ { $size: "$traces" }, 0 ] } })
[
{
_id: ObjectId("6175e7ecc62cff004462d4a6"),
traces: [ [ ObjectId("6175e7ecc62cff004462d4a4") ] ],
caller_address: '0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990'
},
{
_id: ObjectId("6175e7ecc62cff004462d4a7"),
traces: [
[
ObjectId("6175e7ecc62cff004462d4a4"),
ObjectId("6175e7ecc62cff004462d4a4")
],
[ ObjectId("6175e7ecc62cff004462d4a4") ]
],
caller_address: '0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990'
}
]
Найдите более 1 следа
Если вместо этого я хочу найти более одной трассировки, я просто слегка изменяю запрос:
db.CallerTraces.find({ $expr: { $gt: [ { $size: "$traces" }, 1 ] } })
... и это возвращает следующие результаты:
Enterprise replSet [primary] barrydb> db.CallerTraces.find({ $expr: { $gt: [ { $size: "$traces" }, 1 ] } })
[
{
_id: ObjectId("6175e7ecc62cff004462d4a7"),
traces: [
[
ObjectId("6175e7ecc62cff004462d4a4"),
ObjectId("6175e7ecc62cff004462d4a4")
],
[ ObjectId("6175e7ecc62cff004462d4a4") ]
],
caller_address: '0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990'
}
]
Вывод
При попытке оценить длину массива в процессоре запросов мы должны выбрать использование $eval
опция в качестве синтаксиса для MQL не учитывает ваш вариант использования. То $eval
это своего рода универсальный вариант для вещей, которые плохо вписываются в рамки MQL.
ОБНОВЛЕНИЕ № 1
ОП ввела дополнительные требования. Вместо того, чтобы смотреть на количество массивов, мы должны учитывать количество массивов внутри массива (вложенный внутренний массив). Поскольку метод find() с $expr не может оценивать вложенные массивы, мы должны вместо этого использовать структуру агрегации и развернуть внешний массив. В этом примере исходная форма сохраняется в новом поле под названием original
затем заменяет root после завершения всей оценки. Поскольку размотка может привести к дубликатам в конвейере, мы завершаем работу с группой $, чтобы подавить дубликаты.
Решение
db.CallerTraces.aggregate([
{
$addFields: {
"original._id": "$_id",
"original.traces": "$traces",
"original.caller_address": "$caller_address"
}
},
{
$unwind: "$traces"
},
{
$match: { $expr: { $gt: [ { $size: "$traces" }, 1 ] } }
},
{
$replaceRoot: { newRoot: "$original" }
},
{
$group:
{
_id: "$_id",
traces: { "$first": "$traces" },
caller_address: { "$first": "$caller_address" }
}
}
])