sql >> データベース >  >> NoSQL >> MongoDB

MongoDBの値の代わりにキー名をクエリしてフィルタリングする

    これは、mapReduce を使用して行うことができます。 :

    ルートレベルでフィールド名だけを取得するには:

    db.collection.mapReduce(function () {
        Object.keys(this).map(function(key) {
            if (key.match(/^fk/)) emit(key, null);
    
            // OR: key.indexOf("fk") === 0
        });
    }, function(/* key, values */) {
        // No need for params or to return anything in the 
        // reduce, just pass an empty function.
    }, { out: { inline: 1 }});
    

    これにより、次のように出力されます:

    {
        "results": [{
            "_id": "fkKey1",
            "value": null
        }, {
            "_id": "fkKey2",
            "value": null
        }, {
            "_id": "fkKey3",
            "value": null
        }],
        "timeMillis": W,
        "counts": {
            "input": X,
            "emit": Y,
            "reduce": Z,
            "output": 3
        },
        "ok" : 1
    }
    

    フィールド名とその値の一部またはすべて(ドキュメント全体)を取得するには:

    db.test.mapReduce(function () {
        var obj = this;
    
        Object.keys(this).map(function(key) {
            // With `obj[key]` you will get the value of the field as well.
            // You can change `obj[key]` for:
            //  - `obj` to return the whole document.
            //  - `obj._id` (or any other field) to return its value.
    
            if (key.match(/^fk/)) emit(key, obj[key]);
        });
    }, function(key, values) {
        // We can't return values or an array directly yet:
    
        return { values: values };
    }, { out: { inline: 1 }});
    

    これにより、次のように出力されます:

    {
        "results": [{
            "_id": "fkKey1",
            "value": {
                "values": [1, 4, 6]
            }
        }, {
            "_id": "fkKey2",
            "value": {
                "values": ["foo", "bar"]
            }
        }],
        "timeMillis": W,
        "counts": {
            "input": X,
            "emit": Y,
            "reduce": Z,
            "output": 2
        },
        "ok" : 1
    }
    

    サブドキュメントのフィールド名を取得するには(パスなし):

    これを行うには、store JavaScript functions on the Server

    db.system.js.save({ _id: "hasChildren", value: function(obj) {
        return typeof obj === "object";
    }});
    
    db.system.js.save({ _id: "getFields", value: function(doc) {
        Object.keys(doc).map(function(key) {
            if (key.match(/^fk/)) emit(key, null);
    
            if (hasChildren(doc[key])) getFields(doc[key])
        });
    }});
    

    マップを次のように変更します:

    function () {
        getFields(this);
    }
    

    次に、db.loadServerScripts()を実行します それらをロードします。

    サブドキュメントのフィールド名を取得するには(パス付き):

    以前のバージョンでは、フィールド名を返すだけで、それらを取得するためのパス全体ではありません。これは、キーの名前を変更する場合に必要になります。パスを取得するには:

    db.system.js.save({ _id: "getFields", value: function(doc, prefix) {
        Object.keys(doc).map(function(key) {
            if (key.match(/^fk/)) emit(prefix + key, null);
    
            if (hasChildren(doc[key]))
                getFields(doc[key], prefix + key + '.')
        });
    }});
    

    マップを次のように変更します:

    function () {
        getFields(this, '');
    }
    

    重複するパスの一致を除外するには:

    fkfoo.fkbarフィールドがある場合は注意してください 、fkfooを返します およびfkfoo.fkbar 。パスの一致を重複させたくない場合は、次のようにします。

    db.system.js.save({ _id: "getFields", value: function(doc, prefix) {
        Object.keys(doc).map(function(key) {
            if (hasChildren(doc[key]))
                getFields(doc[key], prefix + key + '.')
            else if (key.match(/^fk/)) emit(prefix + key, null);
        });
    }});
    

    質問に戻り、これらのフィールドの名前を変更します:

    この最後のオプションを使用すると、fkで始まるキーを含むすべてのパスを取得できます 、したがって、 $renameを使用できます。 そのために。

    ただし、$rename 配列を含むものでは機能しないため、を使用できます。 forEach 更新を行います。 MongoDBの配列内のデータベースフィールドの名前変更

    パフォーマンスノート:

    MapReduceはそれほど速く考えられていないため、{ out: "fk_fields"}を指定することをお勧めします。 結果をfk_fieldsという新しいコレクションに出力します 後でそれらの結果をクエリしますが、それはユースケースによって異なります。

    特定のケースで可能な最適化(一貫したスキーマ):

    また、ドキュメントのスキーマが常に同じであることがわかっている場合は、そのうちの1つをチェックしてフィールドを取得するだけでよいので、limit: 1を追加して行うことができます。 オプションオブジェクトに移動するか、findOne アプリケーションレベルでそのフィールドを読み取ります。



    1. RedisおよびSpringDataRedisでSSLを使用すると、Jedis接続を取得できません

    2. node.jsアプリのMongoIDに基づいてMongoDBをクエリする

    3. NodeJS0.10.8へのMongooseのインストール

    4. CDPオペレーショナルデータベースの高可用性(マルチAZ)