2017-10-16 2 views
0

データ構造で始まります「Android 5.0」、「Android 6.0」、「Windows Phone」、「Windows Phone 8.1」MongoDBのプロパティ文字列は、クエリやセットグループID

オペレーティングシステムの種類のみを含むプロパティはありません。のみAndroid


私は、Windowsの電話とアンドロイドの電話の数を取得する必要があります。

私の一時的な解決策:

db.getCollection('RB').find(
    {OPERATINGSYSTEM: {$regex: "^Android"}} 
).count(); 

私は多くの時間がかかり、並行して実行する必要がある上でのWindows Phoneとそうで"^Android"を交換し、そのクエリをやっています。

これについていえ集約フレームワークIの使用:

db.RB.aggregate(
{$group: {_id: {OPERATINGSYSTEM:"$OPERATINGSYSTEM"}}},) 

をしかし、これを使用して、私は...

私がすべきを探してる解決策をそれぞれのOperatingSystemバージョンAndroid 5.0Android 6.0などのためのエントリを取得します

{ 
    "Android": 50, 
    "Windows Phone": 100 
} 

これを単一のクエリでどのように行うことができますか?

答えて

0

map reduceを使用して、マップ機能でロジックを適用できます。あなたの文字列が、少なくとも一貫し、その後、あなたは「スペース区切り」から配列を作るために集約フレームワークで$splitを使用することができ、文字列の最後の事のように数値バージョンを持って提供https://docs.mongodb.com/manual/tutorial/map-reduce-examples/

+0

この場合、アグリゲーションフレームワークは最適なソリューションではありません。 –

2

var map = function(){ 
    var name = this.op.includes("android") ? "Android" : ""; // could be a regexp 

    if(name === ""){ 
     name = this.op.includes("windows") ? "Windows" : ""; 
    } 

    emit(name, 1); 
} 

var reduce = function(key, values){ 
    return Array.sum(values) 
} 

db.operating.mapReduce(map, reduce, {out: "total"}) 

コンテンツ、その後、再構築する前に、配列から最後の要素を削除します。

を考えると、データのように:

{ "name" : "Android 6.0" } 
{ "name" : "Android 7.0" } 
{ "name" : "Windows Phone 10" } 

あなたは試すことができます。すべてのことが可能です

db.getCollection('phones').aggregate([ 
    { "$group": { 
    "_id": { 
     "$let": { 
     "vars": { "split": { "$split": [ "$name", " " ] } }, 
     "in": { 
      "$reduce": { 
      "input": { "$slice": [ "$$split", 0, { "$subtract": [ { "$size": "$$split" }, 1 ] } ] }, 
      "initialValue": "", 
      "in": { 
       "$cond": { 
       "if": { "$eq": [ "$$value", "" ] }, 
       "then": "$$this", 
       "else": { "$concat": [ "$$value", " ", "$$this" ] } 
       } 
      } 
      } 
     } 
     } 
    }, 
    "count": { "$sum": 1 } 
    }}, 
    { "$replaceRoot": { 
    "newRoot": { 
     "$arrayToObject": [[{ "k": "$_id", "v": "$count" }]] 
    } 
    }} 
]) 

をあなたのMongoDBは$split$reduceの両方をサポートするために、少なくともMongoDBは3.4である場合。 $replaceRootは本当にキーの名前をつけることであり、実際には必要ありません。

代わりに、あなたはmapReduceを使用することができます:それは簡単だ

db.getCollection('phones').mapReduce(
    function() { 
    var re = /\d+/g; 
    emit(this.name.substr(0,this.name.search(re)-1),1); 
    }, 
    function(key,values) { return Array.sum(values) }, 
    { "out": { "inline": 1 } } 
) 

を数値が発生したインデックスで文字列を打破します。いずれの場合でも、何も "ハードコード"する必要はなく、キーの値は文脈の中の文字列に完全に依存しています。

可能な値が非常に多い場合を除き、カーソルの数を返すので集計されたエントリを実際にカウントするよりも速く処理する必要があります。