1. 程式人生 > >關於Spring-Data-Mongodb中的project()的用法,和previousOperation()的用法

關於Spring-Data-Mongodb中的project()的用法,和previousOperation()的用法

最近使用Spring-Data-Mongodb的API來改寫原來的程式碼,遇到了一些問題,先把自己學到的一些東西總結下來。

參考:

http://www.cnblogs.com/ontheroad_lee/p/3756247.html  (這個文章特別好,很少有中文的關於Spring-Data-Mongodb的API的例子的介紹)

http://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo.aggregation.examples.example6 (官方文件)

1,project("name", "netPrice")

    project方法的內容是你要對映的欄位,相當於{$project: {sumfavour: 1, userid: 1}}。“對映”的意思,就是要顯示哪個欄位,或者把某個欄位內容進行處理後顯示。

2,project().and("foo").as("bar")

    如果你想要把一個欄位對映成別一個名字的話,就可以用上面的方法,相當於{$project: {bar: $foo}}

3,project("a","b").and("foo").as("bar")

    這個方法相當於上面兩個方法的結合{$project: {a: 1, b: 1, bar: $foo}}。如果單獨使用and(),後面不使用as()的話,沒有任何效果,也不會出錯。

4,project().and("_id").plus(100000000).as("statusid")

    這個語句的意思是,把_id欄位加上100000000,再重新命名為"statusid"然後輸出。

5,關於previousOperation()方法

Aggregation agg = newAggregation(
    project("tags"),
    unwind("tags"),
    group("tags").count().as("n"),
    project("n").and("tag").previousOperation(),
    sort(DESC, "n")

);

    這段程式碼中主要講的是previousOperation()方法的使用,想知道其它語句的含義,請參考官網文章介紹。說previousOperation之前要先說說Group語句,這裡的Group語句的作用是,按“tags”欄位進行分組,然後統計每個分組中的資料個數,統計的個數欄位命名為“n”。輸出的結果為(這裡只為貼上了所有資料中的一條):

{

    "_id" : "627",

   "n" : NumberInt(16)
}

project語句的作用是,把新生成的欄位”n“做為結果輸出,並且”_id“列重新命名為”tag“,然後也做為結果輸出,最後結果為:

{

    "tag" : "627",

   "n" : NumberInt(16)
}

看完結果後,我們來說一下previousOperation()的作用。previousOperation()就是把“上一次操作的結果中”的_id欄位,命名為它前面and()中的名稱。所以它一般都是和and()結合使用。關於Group操作後,_id的內容的介紹,請看最下面的“關於_id欄位”說明。

6,

TypedAggregation<ZipInfo> aggregation = newAggregation(ZipInfo.class,
    group("state","city").sum("population").as("pop"),
    sort(ASC,"pop","state","city"),
    group("state").last("city").as("biggestCity").last("pop").as("biggestPop").first("city").as("smallestCity").first("pop").as("smallestPop"),
    project().and("state").previousOperation().and("biggestCity").nested(bind("name","biggestCity").and("population","biggestPop")).and("smallestCity").nested(bind("name","smallestCity").and("population","smallestPop")),
    sort(ASC,"state"));
通過nested()方法,可以把輸出的結果變成巢狀格式,例如:

    "object":{ "fieldA":"valueA","fieldB":"valueB"}

bind()方法是用通過已經存在的欄位,來生成新的欄位。例如

    and("biggestCity").nested(bind("newField", "existField"))

7,

TypedAggregation<Product> agg = newAggregation(Product.class,
    project("name","netPrice").and("netPrice").plus(1).as("netPricePlus1").and("netPrice").minus(1).as("netPriceMinus1").and("netPrice").multiply(1.19).as("grossPrice").and("netPrice").divide(2).as("netPriceDiv2").and("spaceUnits").mod(2).as("spaceUnitsMod2"));
可以在對映完某個欄位後,還可以對欄位進行加減乘除。

8,

TypedAggregation<Product> agg = newAggregation(Product.class,
    project("name","netPrice").andExpression("netPrice + 1").as("netPricePlus1").andExpression("netPrice - 1").as("netPriceMinus1").andExpression("netPrice / 2").as("netPriceDiv2").andExpression("netPrice * 1.19").as("grossPrice").andExpression("spaceUnits % 2").as("spaceUnitsMod2").andExpression("(netPrice * 0.8  + 1.2) * 1.19").as("grossPriceIncludingDiscountAndCharge"));
還可以用andExpression()方法,使用一些mongo中的函式,例如:substr等。更重要的一點,還可以使用SpringSpEL表示式。上面的例子就是使用了表示式。下面是使用和不使用表示式的例子:

使用表示式:

  1+(q +1)/(q -1)
不使用表示式:
  {"$add":[1,{"$divide":[{"$add":["$q",1]},{"$subtract":["$q",1]}]  }]}

而且,而且,在表示式內部還可以設定用外部變數進行替換。

TypedAggregation<Product> agg = newAggregation(Product.class,
    project("name","netPrice").andExpression("(netPrice * (1-discountRate)  + [0]) * (1+taxRate)", shippingCosts).as("salesPrice"));
[0]的位置,就會被後面的shippingCosts引數的內容給替換。

關於_id欄位

    _id欄位是插入到資料庫時自動生成的。在使用Group等聚合操作後,_id的內容會隨著變化。例如:

1,{$group:{_id:'$statusid', sumfavour:{$sum:1}}}

這個語句的意思是,按照statusid欄位進行分組,並統計每個分組的資料個數,被統計的個數欄位命名為“sumfavour”。

從下面的輸出的內容可以看到,_id內容就是statusid欄位的內容。

{
    "sumfavour" : NumberInt(16),
    "statusid" : "627"
}

2,{$group:{_id:{'statusid':'$statusid','userid':'$userid'}, sumfavour:{$sum:1}}}

這個語句的意思是按兩個欄位的內容進行排序。當以兩個或以上的欄位進行分組時,必須這麼寫,下面的例子都是錯誤的:

X:$group:{_id:{'$statusid','$userid'}}

X:$group:{_id:{'statusid','userid'}}

從這次分組完後的內容可以看到,_id的內容是statusid和userid兩個欄位的內容的組合。

{
    "_id" : {
        "statusid" : NumberInt(538),
        "userid" : NumberInt(416347)
    },
    "sumfavour" : NumberInt(1)
}

可以看出_id欄位