2016-03-31 35 views
3

我在mongoDB中有這個查詢,並且產生我想要的結果。但現在我試圖在java中使用它。如何用Java運行.group()

這是MongoDB中查詢:

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

現在我用它在Java中的方式,但我不知道如何使用平均功能。

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); 

如何使用該功能?

回答

1

你會使用這個aggreation框架不是調用​​方法,這當然是實際存在的聚合框架之前的老的實現會更好。

在外殼應用將是邏輯:

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

聚集框架作爲一個非常有效的$group管道檔操作它確實在本地編碼操作都是一樣的東西。內置有$sum$avg累加器以及其他數學運算。

簡而言之,作爲「本地編碼」而不依賴於「JavaScript解釋」,執行速度比.group()可提供的要快得多。另外,它應該是相當直接的理解。

翻譯是到Java會像

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

,但我知道我必須使用聚合框架的解決方案,我需要地圖相同的結果降低到比較...我需要使用Java調用這兩種情況。 – duknust

+1

@duknust你爲什麼認爲你需要mapReduce?這裏的解釋告訴你,使用'.aggregate()它不僅「更容易」,它實際上是遠遠更好的表現。 mapReduce不可能通過'.aggregate()'與性能或規模進行競爭。你也得到了Java代碼。你的評論表明你還沒有完全閱讀答案。我建議你這樣做,並學習它的教訓。 –

+1

@duknust當然,這裏的另一件事是你的編碼函數以及你在shell中嘗試的是''.group()'](https://docs.mongodb.org/manual/reference/method /db.collection.group/)方法。所以即使是JavaScript代碼也需要進行相當大的修改才能適應已經編碼過的mapReduce。所以你要麼在Java中調用'.group()',要麼改變'mapReduce'的所有代碼。但是這裏總的概要是你不應該這樣做。如圖所示使用'.aggregate()'。這太好了。這就是你想要在這裏學習的東西。 –