Mongodb: İç içe dizilerin boyutunu sorgula

0

Soru

Aşağıdaki Şemaya sahibim:

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

});

Ve yalnızca belirli bir numaradan daha büyük Çağrı miktarına sahip izleri olan nesneleri almak istiyorum. Başka bir deyişle, en az bir iç içe geçmiş izleme dizisinin boyutu belirtilen sayıdan büyük olmalıdır. $elemMatch ve $ size kullanmaya çalışıyorum ama başarılı olamadım. Şimdilik bu kodum var.:

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

Burada minTraceSize bir int.

Bana yardım edebilir misiniz? Gerçekten minnettar olurum!

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

En iyi cevabı

0

Örnek veriler için teşekkürler. Cevabım bir mongoose çözümü değil, ham bir MQL çözümü olacak, bu yüzden bazı çeviri gerekli olacak.

Gönderinizdeki yorumlarınıza dayanarak iki belge ekleyebildim. İki örnek belgeden birinin objectıd'sini değiştirmek zorunda kaldım çünkü örnekleriniz aynı birincil anahtar değerine sahipti ve yinelenen bir anahtar istisnası oluşturuyordu.

Örnek Veri Ekleme

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

Dizide 0'dan fazla öğeye sahip kayıtları bulmak istersem traces Aşağıdakileri yayınlayabilirim:

Sıfırdan fazla iz bulma

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

Bu, aşağıdakileri döndürür:

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'den fazla izleme bul

Bunun yerine birden fazla iz bulmak istersem sorguyu biraz değiştiririm:

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

... ve bu aşağıdaki sonuçlarla geri döner:

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

Sonuç

Sorgu işlemcisindeki dizinin uzunluğunu değerlendirmeye çalışırken, aşağıdakileri kullanmayı seçmeliyiz: $eval MQL sözdizimi olarak seçenek kullanım durumunuzu dikkate almaz. Bu $eval bu, MQL çerçevesine tam olarak uymayan şeyler için bir çeşit yakalama seçeneğidir.

GÜNCELLEME #1 OP ek gereksinimler getirdi. Dizinin sayısına bakmak yerine, dizinin içindeki dizinin sayısını (iç içe geçmiş iç dizi) dikkate almalıyız. $ Expr ile find() yöntemi iç içe geçmiş dizileri değerlendiremediğinden, bunun yerine toplama çerçevesini kullanmalı ve dış diziyi çözmeliyiz. Bu örnek, özgün formu adı verilen yeni bir alanda depolar original ardından, tüm değerlendirme tamamlandıktan sonra kök yerini alır. Çözülme, boru hattında çoğaltmalara neden olabileceğinden, çoğaltmaları bastırmak için bir $grubuyla sonuçlandırırız.

Çözüm

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

Merhaba, hızlı yanıtınız için teşekkür ederiz! Ama sorun henüz tam olarak değil... İkinci yuvalama seviyesinde İz boyutlarını almak istiyorum. Yani, eğer varsa: { "_ıd": ObjectId("6175e7ecc62cff004462d4a7"), "izler": [ [ ObjectId("6175e7ecc62cff004462d4a4"), ObjectId("6175e7ecc62cff004462d4a4") ] ], "caller_address": "0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990" }) 2 değerini minTraceSize değişkenine ayarladığımda bu nesne geri dönmelidir.
Bruno Medeiros

@ BrunoMedeiros-lütfen gönderimdeki güncellemelere bakın.
barrypicker

işe yaradı! Çok teşekkür ederim! =)
Bruno Medeiros

Diğer dillerde

Bu sayfa diğer dillerde

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