Soru Mongo karmaşık sıralama?


MongoDB'de sorguları birden çok alanla nasıl sıralayacağımı biliyorum, ör. db.coll.find().sort({a:1,b:-1}).

Kullanıcı tanımlı bir işlevle sıralayabilir miyim; örneğin, a ve b'nin, tam sayıları, a ve b arasındaki fark ile (a-b)?

Teşekkürler!


32
2017-07-09 13:19


Menşei


Aynı konuya koşuyorum. Bunu sunucu tarafında gerçekleştirmenin bir yolunu bulabildiniz mi? Bunu istemcide yapmak zorunda kalmamayı veya ek alan eklemeyi tercih ederim. - Rex Morgan


Cevaplar:


GÜNCELLEŞTİRME: Bu cevap güncel değil gibi görünüyor; Özel sıralama, az veya çok $project toplama hattının işlevi giriş belgelerini sıralamadan önce dönüştürmek için. @ Ari'nin cevabına da bakınız.

Bunun doğrudan mümkün olduğunu düşünmüyorum; belgeleri sırala kesinlikle bir özel karşılaştırma işlevi sağlamak için herhangi bir şekilde söz etmiyor.

Muhtemelen istemcideki işi yapmaktan daha iyisindir, ancak sunucuda yapmaya gerçekten karar verdiyseniz, db.eval() sunucudaki sıralamayı çalıştırmak için (istemciniz destekliyorsa).

Sunucu tarafı sıralama:

db.eval(function() { 
  return db.scratch.find().toArray().sort(function(doc1, doc2) { 
    return doc1.a - doc2.a 
  }) 
});

Eşdeğer istemci tarafı sıralamasında:

db.scratch.find().toArray().sort(function(doc1, doc2) { 
  return doc1.a - doc2.b 
});

Ayrıca bir sırayla sıralamak mümkün olduğunu unutmayın toplama hattı ve tarafından $orderby Şebeke (yanı .sort()Ancak, bu yollardan hiçbiri de özel sıralama işlevi sağlamaz.


29
2017-07-09 14:26



Evet. Daha fazla kazma işleminden sonra, kolaylık fonksiyonlarının tam olarak bunu yapmasını sağlayan bir RFE'nin bulunduğunu tespit ettim. Bunun görünüşünü kesinlikle beğenmedim toArray() ~ 10m belgelerim için, ama görünüşe göre olayların durumu. - gilesc
Merhaba @gilesc. Lütfen bana 'RFE'nin nasıl yapıldığını tam olarak nasıl anlattığınızı anlatır mısınız? Ben aynı durumdayım. - dotslashlu
@Wasabi Ben buna atıfta olduğunu düşünüyorum: jira.mongodb.org/browse/SERVER-153  Bu mümkün değil, ancak uygulamayı düşündükleri bir bilet var. Ama yıllardır açık, bu yüzden hiç gerçekleşmeyeceğinden emin değilim. - rmarscher
Sıralama fonksiyonunuz yanlış olabilir. Olmalı return (doc1.a - doc1.b) - (doc2.a - doc2.b) - Yuanhang
@ Ari'nin cevabında gösterildiği gibi, işlevinizi uygulamak ve bir alana atamak için $ projesini kullanabilir ve ardından bunu sıralayabilirsiniz. - Bob Kerns


Bu işe koyuldu ve ben de bu:

db.collection.aggregate([
  { 
    $project: {
      difference: { $subtract: ["$a", "$b"] }
      // Add other keys in here as necessary
    }
  },  
  { 
    $sort: { difference: -1 } 
  }
])

15
2017-10-21 22:38





Neden bu işlemle alanı yaratmıyor ve üzerine yazmıyorsunuz?


11
2017-07-09 13:25



Hala a ve b'ye erişime ihtiyacım var. Yani üçüncü bir alan yaratmak zorundayım. Bu benim başvurum için işe yarardı, ama genel bir ilke olarak gerçekten kötü bir politika olurdu. Birden fazla tamsayı alanım olduğunu varsayalım, türetilmiş özniteliklerin (a-b), (a-c), (a-d) bir kombinasyon patlaması olacaktır ... Böyle bir alanla bile, özellikle büyük bir koleksiyon için gerçekten boş bir yer. Tereddüt ediyorum ve başka kimse kabul etmeyi kabul etmiyorsa, ama daha iyi bir yol olmalı. SQL'de bu kadar kolay SELECT * FROM coll ORDER BY (a-b) . - gilesc
Bunu SQL'de yapabilmenize rağmen, çok verimli olmadığını unutmayın. Veritabanının tüm a ve b değerlerini alması, a-b değerini hesaplaması, sonuçları sıralaması ve ilgili kayıtları geri göndermesi gerekir. Mongo ile bu, a ve d üzerinde bir diziniz yoksa tüm belgeleri belleğe yüklemek anlamına gelir. Yeni bir alan oluşturursanız, bu sorguyu gerçekten hızlı yapacak olan bir alan oluşturabilirsiniz. - konrad
İyi fikir. Bir kaydın konumunun değeri, kayıttaki verilere yerelleştirildiği sürece, bu, ekleme / güncelleme işleminde sıralama hesaplama maliyetini mükemmel bir şekilde amorti eder. - DoctorPangloss