2013-02-09 12 views
8

Rozważmy następujący przykład:

db.article.aggregate(
    { $group : { 
     _id : "$author", 
     docsPerAuthor : { $sum : 1 }, 
     viewsPerAuthor : { $sum : "$pageViews" } 
    }} 
); 

przez pole autor tej grupie i oblicza dwa pola.

Mam wartości dla $ author = FirstName_LastName. Teraz zamiast grupowania według $ author, chcę grupować według wszystkich autorów, którzy dzielą tę samą Nazwę.

Próbowałem $ regex do grupy wszystkich pasujących ciągów po „_”

$author.match(/_[a-zA-Z0-9]+$/) 

db.article.aggregate(
    { $group : { 
     _id : "$author".match(/_[a-zA-Z0-9]+$/), 
     docsPerAuthor : { $sum : 1 }, 
     viewsPerAuthor : { $sum : "$pageViews" } 
    }} 
); 

also tried the following: 

db.article.aggregate(
    { $group : { 
     _id : {$author: {$regex: /_[a-zA-Z0-9]+$/}}, 
     docsPerAuthor : { $sum : 1 }, 
     viewsPerAuthor : { $sum : "$pageViews" } 
    }} 
); 

Odpowiedz

6

Właściwie nie ma takiej metody, która przewiduje tego rodzaju funkcjonalność lub nie mogłem znaleźć odpowiednią wersję, która zawiera go. To nie zadziała z $ regexp myślę, że: http://docs.mongodb.org/manual/reference/operator/regex/ służy tylko do dopasowywania wzorców.

Jest prośba poprawa JIRA: https://jira.mongodb.org/browse/SERVER-6773

Jest w stanie otwartym nierozwiązany. ALE

w github Znalazłem dyskusyjne: https://github.com/mongodb/mongo/pull/336

A jeśli to sprawdzić popełnić: https://github.com/nleite/mongo/commit/2dd175a5acda86aaad61f5eb9dab83ee19915709

zawiera więcej lub mniej dokładnie metoda prawdopodobnie mieć. Naprawdę nie rozumiem stanu tej poprawy: w 2.2.3 to nie działa.

+0

dzięki. Przekażę to na jira.mongodb.org – user1447121

4

Użyj mapReduce: jest to ogólna forma agregacji. Jest to, jak postępować w Mongo skorupy: zdefiniować funkcję mapie

var mapFunction = function() { 
    var key = this.author.match(/_[a-zA-Z0-9]+$/)[0]; 
    var nb_match_bar2 = 0; 
    if(this.bar.match(/bar2/g)){ 
    nb_match_bar2 = 1; 
    } 
    var value = { 
    docsPerAuthor: 1, 
    viewsPerAuthor: Array.sum(this.pageViews) 
    }; 

    emit(key, value); 
}; 

a funkcja

var reduceFunction = function(key, values) { 

    var reducedObject = { 
    _id: key, 
    docsPerAuthor: 0, 
    viewsPerAuthor: 0 
    }; 

    values.forEach(function(value) { 
    reducedObject.docsPerAuthor += value.docsPerAuthor; 
    reducedObject.viewsPerAuthor += value.viewsPerAuthor; 
    } 
); 
    return reducedObject; 
}; 

run mapreduce zmniejszyć i zapisać wynik w map_reduce_result

>db.st.mapReduce(mapFunction, reduceFunction, {out:'map_reduce_result'}) 

zapytania map_reduce_result do mieć wynik

>db.map_reduce_result.find() 
3

Możliwe obejście ze schematem agregacji polega na użyciu projektu $ do obliczenia nazwy autora. Jest jednak brudny, ponieważ musisz ręcznie przechodzić między różnymi rozmiarami pierwszych imion:

Tutaj obliczamy nazwę pola jako podciąg po znaku "_", próbując każdej z możliwych pozycji (dlatego właśnie jest łańcuch $ dyr) i fallbacking w powrocie całą $ autor, jeśli pierwsza nazwa jest zbyt długa:

http://mongotry.herokuapp.com/#?bookmarkId=52fb5f24a0378802003b4c68

[ 
{ 
    "$project": { 
     "author": 1, 
     "pageViews": 1, 
     "name": { 
      "$cond": [ 
       { 
        "$eq": [ 
         { 
          "$substr": [ 
           "$author", 
           0, 
           1 
          ] 
         }, 
         "_" 
        ] 
       }, 
       { 
        "$substr": [ 
         "$author", 
         1, 
         999 
        ] 
       }, 
       { 
        "$cond": [ 
         { 
          "$eq": [ 
           { 
            "$substr": [ 
             "$author", 
             1, 
             1 
            ] 
           }, 
           "_" 
          ] 
         }, 
         { 
          "$substr": [ 
           "$author", 
           2, 
           999 
          ] 
         }, 
         { 
          "$cond": [ 
           { 
            "$eq": [ 
             { 
              "$substr": [ 
               "$author", 
               2, 
               1 
              ] 
             }, 
             "_" 
            ] 
           }, 
           { 
            "$substr": [ 
             "$author", 
             3, 
             999 
            ] 
           }, 
           { 
            "$cond": [ 
             { 
              "$eq": [ 
               { 
                "$substr": [ 
                 "$author", 
                 3, 
                 1 
                ] 
               }, 
               "_" 
              ] 
             }, 
             { 
              "$substr": [ 
               "$author", 
               4, 
               999 
              ] 
             }, 
             { 
              "$cond": [ 
               { 
                "$eq": [ 
                 { 
                  "$substr": [ 
                   "$author", 
                   4, 
                   1 
                  ] 
                 }, 
                 "_" 
                ] 
               }, 
               { 
                "$substr": [ 
                 "$author", 
                 5, 
                 999 
                ] 
               }, 
               "$author" 
              ] 
             } 
            ] 
           } 
          ] 
         } 
        ] 
       } 
      ] 
     } 
    } 
}, 
{ 
    "$group": { 
     "_id": "$name", 
     "viewsPerAuthor": { 
      "$sum": "$pageViews" 
     } 
    } 
} 
]