Guruhdan faqat oxirgi vaqt tamg'asi bo'lgan hujjatlarni qanday so'rash mumkin?

Men so'ragan MongoDB to'plamida har bir hujjat ma'lum bir vaqtda elementni ifodalaydi. Hujjatni yangilashda bir xil element identifikatori va yangi vaqt tamg'asi bilan yangi hujjat yaratiladi. Barcha elementlar noyob element identifikatorlariga ega.

Tasavvur qilish uchun ushbu misolni ko'rib chiqing. Biz elementni bitta qayta ko'rib chiqishdan boshlaymiz:

{
    _id: x,
    itemId: 123,
    createdOn: ISODate("2013-01-30T11:16:20.102Z"),
    field1: "foo",
    field2: "bar
}

Yangilangandan so'ng bizda bir xil itemId va turli vaqt belgilariga ega bo'lgan elementning ikkita tahriri mavjud.

[{
  _id: x,
  itemId: 123,
  createdOn: ISODate("2013-01-30T11:16:20.102Z"),
  field1: "foo",
  field2: "bar"
},
{
  _id: y,
  itemId: 123,
  createdOn: ISODate("2014-02-09T14:26:20.102Z"),
  field1: "baz",
  field2: "fiz"
}]

Oxirgi tahririda ma'lum bir so'rovni qondiradigan barcha narsalarni qanday topish mumkin?

Mening joriy (noto'g'ri) yondashuvim avvalo mos keladigan hujjatlarni topish, keyin vaqt tamg'asi bo'yicha tartiblash, ularni itemId bo'yicha guruhlash va guruhdagi birinchi hujjatdagi qiymatlarni qaytarishdir:

ItemModel.aggregate({ $match: { field1: "foo"} }).sort({createdOn: -1}).group(
    {
        _id: '$itemId', // grouping key
        createdOn: {$first: '$createdOn'},
        field1: {$first: '$field1'},
        field2: {$first: '$field2'}
    }).exec(...);

Bu notoʻgʻri, chunki u elementlarning eski tahrirlariga mos keladi. Faqat elementlarning so'nggi tahrirlari mos kelishi kerak. Yuqoridagi misolda bu yondashuv "123" bandini qaytaradi, to'g'ri natija esa bo'sh natijalar to'plamidir.


person Per Christian Henden    schedule 10.02.2014    source manba


Javoblar (2)


Bu yerda siz bir nechta usullarni aralashtirasiz, qachonki siz yig'ish quvuridagi hamma narsani qila olasiz. Aks holda, qadamlaringizni to'g'ri tartibda olish kerak:

db.collection.aggregate([
    {$sort: { createdOn: -1 }},
    {$group: { _id: "$itemId", 
        createdOn: {$first: "$createdOn"},
        field1: {$first: "$field1" },
        field2: {$first: "$field2" }
    }},
    {$match: { field1: "foo" }}
])

Shunday qilib, eng yangi hujjatlar uchun avval tartiblang. itemId bo'yicha guruhlang (buyurtma $first uchun saqlanadi), keyin kerak bo'lsa $match bilan filtrlang. Lekin sizning guruhlangan hujjatlaringiz eng so'nggi bo'ladi.

person Neil Lunn    schedule 10.02.2014
comment
Rahmat, men yig'ish quvurining qanchalik moslashuvchanligini tushunmagan edim. Men boshida ham, oxirida ham mos qadam bilan yakunlandim, chunki bu quvur liniyasi orqali o'tadigan hujjatlar sonini kamaytirish orqali ishlashni yaxshilaydi. - person Per Christian Henden; 12.02.2014

Hujjat sxemasini sizning so'rovlaringizga yaxshiroq moslashtirish va yig'ish xarajatlarini kamaytirish uchun o'zgartirishni ko'rib chiqish mumkin. Har bir qayta koʻrib chiqish uchun yangi hujjat yaratish oʻrniga, qayta koʻrib chiqish boʻyicha kichik hujjatlarni massivga surib qoʻyishingiz va asosiy hujjatda oxirgi tahrirni saqlab qolishingiz mumkin; masalan:

{
    _id: x,
    itemId: 123,
    createdOn: ISODate("2014-02-09T14:26:20.102Z"),
    field1: "baz",
    field2: "fiz,
    revisions: [
        {createdOn: ISODate("2013-01-30T11:16:20.102Z"), field1: "foo", field2: "bar"},
        {createdOn: ISODate("2014-02-09T14:26:20.102Z"), field1: "baz", field2: "fiz"}
    ]
}

Shuni yodda tutingki, MongoDB 16 MB hajmdagi hujjat hajmini cheklaydi; Bu ko'p hollarda foydalanish uchun etarli bo'lishi kerak. Bu sizning so'rovlaringizni juda oddiy qiladi: db.collection.find({field1: "foo"})

Yana bir yondashuv...

person Rishi    schedule 10.02.2014
comment
Rahmat! Bu yaxshi fikr, chunki so'rovlarni hisoblashda joriy sxema ham muammoli. To'g'ri elementlar sonini olish uchun butun yig'ish quvurini ishga tushirishim kerak edi. - person Per Christian Henden; 12.02.2014