13

MongoDBにドキュメントがあり、そのうちの1つは次のようになります。

{
"_id" : 100,
"name" : "Something",
"items" : [
    {
        "item" : 47,
        "color" : "red"
    },
    {
        "item" : 44,
        "color" : "green"
    },
    {
        "item" : 39,
        "color" : "blue"
    }
]
}

すべてのドキュメントで、最小限のアイテムを見つけて削除する必要があります。したがって、次のようになります。

{
"_id" : 100,
"name" : "Something",
"items" : [
    {
        "item" : 47,
        "color" : "red"
    },
    {
        "item" : 44,
        "color" : "green"
    }
]
}

ここでは関数を使用する必要があるようfindAndModifyですが、これ以上先に進むことはできません。

配列内の最小要素を見つけて削除するにはどうすればよいですか?

MongoDBとPymongoドライバーを使用しています。

4

3 に答える 3

18

クエリを1つのステップに制限されていない場合は、次のことを試すことができます。

ステップ1)$unwindおよび$group演算子で集計関数を使用して、各ドキュメントの最小アイテムを見つけます

myresults = db.megas.aggregate( [ { "$unwind": "$items" },  
    {"$group": { '_id':'$_id' , 'minitem': {'$min': "$items.item" } } } ] )

ステップ2)結果をループし、配列から要素を$pullします

for result in myresults['result']:
    db.megas.update( { '_id': result['_id'] }, 
        { '$pull': { 'items': { 'item': result['minitem'] } } } )
于 2012-11-12T17:58:23.847 に答える
9

プレーンなJavaScriptで書かれた私の解決策を見つけてください。MongoDbシェルを介して直接機能するはずです

cursor = db.students.aggregate(
[{ "$unwind": "$items" }, 
 { "$match": { "items.color": "green"}},
 { "$group": {'_id': '$_id', 'minitem': {
                '$min': "$items.item"
            }
        }
    }

]);

cursor.forEach(
function(coll) {
    db.students.update({
        '_id': coll._id
    }, {
        '$pull': {
            'items': {
                'item': coll.minitem
            }
        }
    })
})
于 2015-01-25T19:25:41.320 に答える
0

からMongo 4.4$function集約演算子を使用すると、カスタムjavascript関数を適用して、MongoDBクエリ言語でサポートされていない動作を実装できます。

db.collection.update()そして、それに加えられた改善と相まってMongo 4.2、集約パイプラインを受け入れることができ、それ自体の値に基づいてフィールドを更新できるようになります。

言語で簡単に許可されない方法で配列を操作および更新できます。

// {
//   "name" : "Something",
//   "items" : [
//     { "item" : 47, "color" : "red"   },
//     { "item" : 39, "color" : "blue"  },
//     { "item" : 44, "color" : "green" }
//   ]
// }
db.collection.update(
  {},
  [{ $set:
    { "items":
      { $function: {
          body: function(items) {
            var min = Math.min(...items.map(x => x.item));
            return items.filter(x => x.item != min);
          },
          args: ["$items"],
          lang: "js"
      }}
    }
  }],
  { multi: true }
)
// {
//   "name" : "Something",
//   "items" : [
//     { "item" : 47, "color" : "red"   },
//     { "item" : 44, "color" : "green" }
//   ]
// }

$function3つのパラメータを取ります:

  • body、これは適用する関数であり、そのパラメーターは変更する配列です。ここでの関数は、最初itemに配列から最小値を見つけてそれを見つけることから成りfilterます。
  • argsbody関数がパラメータとして受け取るレコードのフィールドが含まれています。私たちの場合、"$items"
  • lang, which is the language in which the body function is written. Only js is currently available.
于 2020-03-31T19:00:14.597 に答える