2016-03-31 12 views
3

Bu sorguyu mongoDB'de alıyorum ve istediğim sonucu üretiyor. Ama şimdi onu java'da kullanmaya çalışıyorum. Java ile bir .group() nasıl çalıştırılır

Bu

MongoDB sorgu geçerli:

var red = function(doc, out) { 
out.count_order++; 
out.sum_qty += doc.quantity; 
out.sum_base_price += doc.extendedprice; 
out.sum_disc_price += doc.extendedprice * (1 - doc.discount); 
out.sum_charge += doc.extendedprice * (1 - doc.discount) * (1 + doc.tax); 
out.avg_disc += doc.discount; 
}; 

var avg = function(out) { 
out.avg_qty = out.sum_qty/out.count_order; 
out.avg_price = out.sum_base_price/out.count_order; 
out.avg_disc = out.avg_disc/out.count_order; 
}; 

db.lineitems.group({ 
key : { returnflag : true, linestatus : true}, 
cond : { "shipdate" : {$lte: 19980801}}, 
initial: { count_order : 0, sum_qty : 0, sum_base_price : 0, sum_disc_price : 0, 
sum_charge : 0, avg_disc : 0}, 
reduce : red, 
finalize : avg 
}); 

Ve şimdi Java kullanıyorum yolu ama ort fonksiyonunu nasıl kullanılacağını bilmiyorum.

String avg = "var avg = function(out) {" 
      + "out.avg_qty = out.sum_qty/out.count_order;" 
      + "out.avg_price = out.sum_base_price/out.count_order;" 
      + "out.avg_disc = out.avg_disc/out.count_order;};"; 

    String reduce = "function(doc, out) {" 
      + "out.count_order++;" 
      + "out.sum_qty += doc.quantity;" 
      + "out.sum_base_price += doc.extendedprice;" 
      + "out.sum_disc_price += doc.extendedprice * (1 - doc.discount);" 
      + "out.sum_charge += doc.extendedprice * (1 - doc.discount) * (1 + doc.tax);" 
      + "out.avg_disc += doc.discount;};"; 

    String finalize = "function(out) {" 
      + "out.avg_qty = out.sum_qty/out.count_order;" 
      + "out.avg_price = out.sum_base_price/out.count_order;" 
      + "out.avg_disc = out.avg_disc/out.count_order;};"; 

    MapReduceIterable<Document> iterable = collection.mapReduce(**????**, reduce).finalizeFunction(finalize); 

Bu işlevi nasıl kullanabilirim?

cevap

1

Elbette gerçekten var toplama çerçevesi önce eski bir uygulamasıdır .group() yöntemi, çağırmaktan daha bunun için aggreation çerçevesini kullanarak daha iyi olurdu.

olacaktır kabuk uygulanan mantık:

db.lineitems.aggregate([ 
    { "$match": { "shipdate": { "$lte": 19980801 } }, 
    { "$group": { 
     "_id": { 
      "returnflag": "$returnflag", 
      "linestatus": "$linestatus" 
     }, 
     "count": { "$sum": 1 }, 
     "sum_qty": { "$sum": "$quantity" }, 
     "avg_qty": { "$avg": "$quantity" }, 
     "sum_base_price": { "$sum": "$extendedprice" }, 
     "avg_base_price": { "$avg": "$extendedprice" }, 
     "sum_disc_price": { 
      "$sum": { 
       "$multiply": [ 
        "$extendedprice", 
        { "$subtract": [ 1, "$discount" ] } 
       ] 
      } 
     }, 
     "avg_disc_price": { 
      "$avg": { 
       "$multiply": [ 
        "$extendedprice", 
        { "$subtract": [ 1, "$discount" ] } 
       ] 
      } 
     }, 
     "sum_charge": { 
      "$sum": { 
       "$multiply": [ 
        "$extendedprice", 
        { "$subtract": [ 1, "$discount" ] }, 
        { "$add": [ 1, "$tax" ] } 
       ] 
      } 
     }, 
     "avg_disc": { "$avg": "$discount" } 
    }} 
]) 

doğal kodlu işlemlerinde aynı şeyleri yapan bir çok verimli $group boru hattı aşaması operatörü olarak agregasyon çerçevesi. Diğer matematik işlemlerinin yanı sıra $sum ve $avg akümülatörler de bulunmaktadır. Kısaca, "doğal olarak kodlanmış" ve "JavaScript yorumlamasına" güvenmemekle birlikte, yürütme, .group()'un sağlayabileceğinden çok daha hızlıdır. Artı gerçekten anlamak için oldukça basit olmalı.

Java o çevriliyor olurdu şey biliyorum ama toplama çerçevesini kullanarak bir çözüm var ve ben çağırmak için Java kullanmak gerekir ... karşılaştırmak azaltmak harita ile aynı sonucu ihtiyaç

List<Document> pipeline = Arrays.<Document>asList(
    new Document(
    "$match", new Document(
     "shipdate", new Document(
     "$lte", 19980801    
    ) 
    ) 
), 
    new Document(
    "$group", new Document(
     "_id", new Document(
     "returnflag", "$returnflag" 
    ).append("linestatus", "$linestatus") 
    ).append(
     "count", new Document("$sum", 1) 
    ).append(
     "sum_qty", new Document("$sum", "$quantity") 
    ).append(
     "avg_qty", new Document("$avg", "$quantity") 
    ).append(
     "sum_base_price", new Document("$sum", "$extendedprice") 
    ).append(
     "avg_base_price", new Document("$avg", "$extendedprice") 
    ).append(
     "sum_disc_price", new Document(
     "$sum", new Document(
      "$multiply", Arrays.asList(
      "$extendedprice", 
      new Document(
       "$subtract", Arrays.asList(1, "$discount") 
      ) 
     ) 
     ) 
    ) 
    ).append(
     "avg_disc_price", new Document(
     "$avg", new Document(
      "$multiply", Arrays.asList(
      "$extendedprice", 
      new Document(
       "$subtract", Arrays.asList(1, "$discount") 
      ) 
     ) 
     ) 
    ) 
    ).append(
     "sum_charge", new Document(
     "$sum", new Document(
      "$multiply", Arrays.asList(
      "$extendedprice", 
      new Document(
       "$subtract", Arrays.asList(1, "$discount") 
      ), 
      new Document(
       "$add", Arrays.asList(1, "$tax") 
      ) 
     ) 
     ) 
    ) 
    ).append(
     "avg_disc", new Document("$avg", "$discount") 
    ) 
) 
); 

AggregateIterable<Document> result = collection.aggregate(pipeline); 
+0

gibi Her iki durumda da. – duknust

+1

@duknust Neden haritaya ihtiyacınız olduğunu düşünüyorsunuz? Buradaki açıklama, '.aggregate()' yi kullanarak "daha kolay" olmanın yanı sıra, aslında ** daha ** daha fazla performansın olduğunu gösterir. MapReduce'un ".aggregate()" ile performans veya ölçek üzerinde rekabet etmesi mümkün değildir. Ve Java kodunu da aldınız. Yorumunuz, cevabı tam olarak okumadığınızı gösterir. Yapmanı öneririm ve derslerini öğrenirim. –

+1

@duknust Tabii ki burada diğer bir şey de kodlanmış fonksiyonlarınızın yanı sıra kabukta çalıştığınız şeylerin ['.group()'] için olmasıdır (https://docs.mongodb.org/manual/reference/method /db.collection.group/) yöntemi belirtildiği gibi. Bu yüzden, JavaScript kodu bile 'mapReduce' 'u zaten kodladığınızdan sığdırmak için önemli bir değişiklik yapılmasını gerektirecektir. Bu yüzden ya Java'da '.group()' ı, ya da 'mapReduce' için tüm kodu değiştirirsiniz. Ama genel özeti, bunu yapmamanız gerektiğidir. Gösterildiği gibi '.aggregate() kullanın. Bu daha iyi. Burada öğrenmeniz gereken şey budur. –