質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.34%

  • MongoDB

    255questions

    MongoDBはオープンソースのドキュメント指向データベースの1つです。高性能で、多くのリトルエンディアンシステムを利用することができます。

mongoDBでcountしたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 400

zacintosh

score 4

mongodb version v3.6.1

こういうしょうもない設計のレコードが50万件くらいあります。

{
    "_id" : ObjectId("5a51d36bf7a162fcfea3d119"),
    "detail" : {
        "shop_id" : 3,
        "keyword" : "s_1",
        "s_1" : {
            "hoge" : false,
        }
    }
},
{
    "_id" : ObjectId("5a51d36bf7a162fcfea3d111"),
    "detail" : {
        "shop_id" : 134,
        "keyword" : "s_2",
        "s_2" : {
            "hoge" : true,
        }
    }
},
{
    "_id" : ObjectId("5a51d36bf7a162fcfea3d112"),
    "detail" : {
        "shop_id" : 569,
        "keyword" : "s_3",
        "s_3" : {
            "hoge" : true,
        }
    }
}

これをmongoDB上だけで「"hoge" : true」の数をカウントしたいです。
上記のデータの場合「2」ということになります。

単純にカウントするだけなら簡単なのですが、問題は"detail"のs_1、s_2、s_3が全部uniqueな値なので、単純に

"detail.s_1.hoge" : true


という条件式が書けません。

ただし、s_1、s_2、s_3というフィールド名は、必ず"detail.keyword"の値と同じです。

何か策はないものでしょうか。。。

フィールド名を$renameで変更してtemp collectionを作ろうかとも思ったのですが、やはりs_1、s_2、s_3がuniqueな値であるところでつまづきます。

レコード数が多いのでnode.jsやPHPなどは使わず、mongoDB内で完結するのがミッションです。

 
追記:
いきなりカウントするのは無理そうなので、いったん別のcollectionにフィールド名を修正して書き出そうとしてみました。

まだ途中なのでoutのところは書いていないですが、フィールド名を上書きする部分だけを書いてみました。

db.test.find().forEach(function(doc){
    let shopName = doc.shop_detail.key;
    shopName = "shop_detail." + shopName;
    db.test.update( { "_id" : doc._id }, { "$rename": { shopName:"shop_detail.data" } } );
})


エラーは出ないのですが上書きもされません。
う〜ん、ちょっと行き詰まっているのでどなたか助けてください。。。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

check解決した方法

0

上のコードですが、mongoの$renameはフィールド名に変数を指定できないみたいです。
なので、temp_collectionを別に作って該当のフィールドをrootに追加してから、いらないフィールドを全部削除して"hoge" : trueをカウントしました。

ダミーのcollectionの名前はtestです。

db.test.find().forEach(function(doc){
  let str = doc.detail.keyword;
  let bson = doc["detail"][str];
  db.test.update({"_id" : doc._id},{"$set" : {"data" : bson},"$unset" : {"detail" : 1}});
})


実行すると、

{
    "_id" : ObjectId("5a51d36bf7a162fcfea3d119"),
    "data" : {
        "hoge" : false
    }
}
{
    "_id" : ObjectId("5a51d36bf7a162fcfea3d111"),
    "data" : {
        "hoge" : true
    }
}
{
    "_id" : ObjectId("5a51d36bf7a162fcfea3d112"),
    "data" : {
        "hoge" : true
    }
}


その後、

db.test.find({"data.hoge":true}).count()


で2が返ってきます。

monboDBでフィールド名をuniqueにするのは極力やめましょうw
あー疲れた、3連休が消えた・・・。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • MongoDB

    255questions

    MongoDBはオープンソースのドキュメント指向データベースの1つです。高性能で、多くのリトルエンディアンシステムを利用することができます。