Mongodb: Dotaz na velikost vnořených polí

0

Otázka

Mám následující Schéma:

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

});

A já bych chtěl získat jen objekty, které mají stopy s Hovory množství větší než zadané číslo. Jinými slovy, velikost alespoň jedno vnořené pole stopy by měla být větší než určené číslo. Snažím se používat $elemMatch a $velikost, ale bez úspěchu. Pro teď, mám tento kód:

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

Kde minTraceSize je int.

Mohli byste mi pomoci? Já bych opravdu si toho vážím!

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

Nejlepší odpověď

0

Díky za vzorek údajů. Moje odpověď bude syrové MQL řešení, ne mongoose řešení, takže nějaký překlad bude zapotřebí.

Byl jsem schopen chcete-li vložit dva dokumenty založené na vaše komentáře v příspěvku. Musel jsem změnit ObjectId jednoho z dva ukázkové dokumenty, protože vzorky měly stejnou hodnotu primárního klíče a generování duplicitní klíč výjimkou.

Vložit Ukázková Data

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

Pokud chci najít záznamy, které mají více než 0 položek v poli traces Mohu vydat následující:

Najít více než žádné stopy

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

Tento příkaz vrátí následující:

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

Najít více než 1 stopa

Pokud místo toho jsem chtěl najít více než jednu stopu jsem jednoduše změnit dotaz, mírně:

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

... a tato se vrátí s následujícími výsledky:

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

Závěr

Při pokusu vyhodnotit délku pole v dotazu procesor musíme volit používat $eval možnost jako syntaxe pro MQL nepovažuje váš případ použití. Na $eval je poněkud catch-all volbou pro věci, které se nevejdou pěkně v MQL rámce.

UPDATE #1 OP zavedeny dodatečné požadavky. Spíše než se podívat na počet pole, musíme vzít v úvahu, hrabě z pole do pole (vnořené vnitřní pole). Od find() metoda s $expr nelze hodnotit vnořených polí místo toho musíme použít agregační framework a odpočinout vnější pole. Tento příklad uloží původní podobě v nové pole s názvem original pak nahradí kořen po všech hodnocení je kompletní. Od odvíjení může v důsledku duplicity v potrubí doladíme s $group k potlačení duplicity.

Řešení

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

Dobrý den, Děkuji za vaši rychlou odpověď! Ale není ještě tak docela problém... chci se dostat Stopy velikostí v druhé úrovni vnoření. Takže, když mám: { "_id": ObjectId("6175e7ecc62cff004462d4a7"), "stopy": [ [ ObjectId("6175e7ecc62cff004462d4a4"), ObjectId("6175e7ecc62cff004462d4a4") ] ], "caller_address": "0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990" }) Tento objekt by se měl vrátit, když jsem se nastavit 2 minTraceSize proměnné.
Bruno Medeiros

@BrunoMedeiros - viz aktualizace v mém příspěvku.
barrypicker

to fungovalo! Děkuji moc! =)
Bruno Medeiros

V jiných jazycích

Tato stránka je v jiných jazycích

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