Mongodb: Zapytanie o wielkości zagnieżdżonych tablic

0

Pytanie

Mam następujący schemat:

Schema({
caller_address: {
    type: String,
    required: true,
},
traces: [[{
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Call',
}]]

});

I chciałbym uzyskać tylko te obiekty, które mają śledzenia z ilością połączeń niż podana liczba. Innymi słowy, rozmiar co najmniej jednego załącznika tablicy śladów musi być większa od podanej liczby. Staram się używać $elemMatch i $size, ale bezskutecznie. W tej chwili mam ten kod:

CallerTraces.find({ 'traces' : { $elemMatch: { $size : { $gt: minTraceSize } }}})

Gdzie minTraceSize-to int.

Nie może wy mi w tym pomóc? Byłbym ci bardzo wdzięczny!

arrays mongodb nested
2021-11-23 20:27:28
1

Najlepsza odpowiedź

0

Dziękuję za próbkę danych. Moja odpowiedź będzie surowo rozwiązaniem MQL, a nie rozwiązaniem mangusta, więc trzeba niektóre tłumaczenia.

Udało mi się wstawić dwa dokumentu, na podstawie swoich komentarzach w poście. Musiałem zmienić identyfikator obiektu jednego z dwóch wzorów dokumentów, bo swoje próbki miały taką samą wartość klucza podstawowego i tworzyli wyjątkiem duplikatu klucza.

Włóż Przykłady Danych

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"
})

Jeśli chcę znaleźć rekordy zawierające ponad 0 elementów w tablicy traces Mogę wydać następujący:

Znajdź więcej zero śladów

db.CallerTraces.find({ $expr: { $gt: [ { $size: "$traces" }, 0 ] } })

To zwraca następujący:

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'
  }
]

Znajdź ponad 1 śladu

Jeśli zamiast tego chcę znaleźć więcej niż jedną śledzenia, ja tylko lekko zmienić zapytanie:

db.CallerTraces.find({ $expr: { $gt: [ { $size: "$traces" }, 1 ] } })

... i to zwraca następujące wyniki:

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'
  }
]

Wniosek

Przy próbie oceny długości tablicy w procesor zapytań musimy zdecydować się na stosowanie $eval opcja jako składni dla MQL nie bierze pod uwagę możliwość użycia. To $eval jest to swego rodzaju uniwersalnym rozwiązaniem dla rzeczy, które źle wpisują się w ramy MQL.

AKTUALIZACJA nr 1 OP wprowadziła dodatkowe wymagania. Zamiast patrzeć na ilość tablic, musimy wziąć pod uwagę ilość tablic wewnątrz tablicy (załączony wewnętrzny tablica). Ponieważ metoda find() z $expr nie może oceniać zagnieżdżone tablice, musimy zamiast tego użyj struktury agregacji i wdrożyć zewnętrzny tablicy. W tym przykładzie oryginalna forma jest zachowana w nowym polu o nazwie original następnie zastępuje korzeń po zakończeniu całej oceny. Ponieważ rozwijanie i przenoszenie warstwy materiału może prowadzić do dwóch egzemplarzach w rurociągu, kończymy pracę z grupą $, aby stłumić duplikaty.

Rozwiązanie

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" }
        }
    }
])
2021-11-24 21:42:44

Witam, dziękuję za szybką odpowiedź! Ale to jeszcze nie problem... chcę uzyskać wymiary śladów na drugim poziomie zagnieżdżenia. Tak więc, jeśli mam: { "pola _id": identyfikator obiektu w("6175e7ecc62cff004462d4a7"), "ślady": [ [ identyfikator obiektu w("6175e7ecc62cff004462d4a4"), wartość identyfikator obiektu("6175e7ecc62cff004462d4a4") ] ], "caller_address": "0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990" }) ten obiekt, musisz wrócić, kiedy zainstalowałem 2 do minTraceSize zmiennej.
Bruno Medeiros

@БруноМедейрос - proszę zobaczyć aktualizacje w moim poście.
barrypicker

to zadziałało! Dziękuję bardzo! =)
Bruno Medeiros

W innych językach

Ta strona jest w innych językach

Русский
..................................................................................................................
Italiano
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................