2013-02-09 6 views
8

Betrachten Sie das folgende Beispiel:

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

Diese Gruppen vom Autor Feld und berechnet zwei Felder.

Ich habe Werte für $ author = FirstName_LastName. Nun, statt von $ Author gruppieren, möchte ich von allen Autoren, die den gleichen Nachnamen teilen.

habe ich versucht, $ Regex Gruppe von allen passenden Saiten nach dem ‚_‘

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

Antwort

6

Eigentlich gibt es keine solche Methode, die diese Art von Funktionalität bietet oder ich könnte die entsprechende Version nicht finden, die sie enthält. Das funktioniert nicht mit $ regexp ich denke: http://docs.mongodb.org/manual/reference/operator/regex/ es ist nur für die Mustererkennung.

Es ist eine Verbesserung Anfrage im jira: https://jira.mongodb.org/browse/SERVER-6773

Es ist im offenen Zustand ungelöst.

es enthält mehr oder weniger genau die Methode, die Sie voraussichtlich haben https://github.com/nleite/mongo/commit/2dd175a5acda86aaad61f5eb9dab83ee19915709: ABER

in Github ich diese disscussion gefunden: https://github.com/mongodb/mongo/pull/336

Und wenn Sie diese begehen überprüfen. Ich verstehe den Zustand dieser Verbesserung nicht wirklich: In 2.2.3 funktioniert es nicht.

+0

dank. Ich bringe das auf jira.mongodb.org – user1447121

4

Verwenden Sie mapReduce: Dies ist die allgemeine Form der Aggregation. Dies ist, wie in Mongo Shell vorgehen: der Karte Funktion definieren

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

und die Funktion

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

Lauf verkleinern reduzieren und das Ergebnis in map_reduce_result speichern

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

Abfrage map_reduce_result zu haben das Ergebnis

>db.map_reduce_result.find() 
3

Eine mögliche Problemumgehung mit dem Aggregationsframework besteht in der Verwendung von $ project zur Berechnung des Autornamens. Es ist jedoch schmutzig, da Sie die verschiedenen Größen des Vornamens manuell durchlaufen müssen:

Hier berechnen wir den Feldnamen als Teilzeichenfolge nach dem '_' Zeichen und versuchen jede seiner möglichen Position (deshalb dort ist eine Kette von $ cond) und fallbacking den ganzen $ Autor, wenn der erste Name zu lang ist, bei der Rückkehr:

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