この投稿は、小さなmongodb
チートシートと、いくつかのレシピを使用したmongodb
長いクエリです。 小さなものが1か所に集められていると便利な場合がありますmongodb
興味がある人mongodb
誰でも自分に役立つものを見つけてください。
SQL vs. NOSQL
トピックに関するホリバーのキーで投稿が認識されることは望ましくありません。 SQL vs. NOSQL
そして、どこにでも賛否両論があることは明らかです。この場合、それはどこかに少し助けになり、どこかにあなたが対処しなければならなかったいくつかの例になります。 mongo shell
およびpython
例。
- mongodbの新しいバージョンへの移行
- 比較クエリと論理クエリ
- Mongodb、正規表現、インデックスなどでの全文検索
- 原子演算子(データの変更)
- Mongodbのトランザクションについて少し
- Mongodbの集約フレームワークとJOIN
- 例
- Python小さなサンドボックス
mongodbへの移行
バージョン2.6へ
バージョン2.6
のリリース後、 mongodb
は、データベース、個々のコレクションにユーザー権限を割り当てるための新しいシステムを追加しました。 そして、それに応じて、更新時にはこれを考慮に入れる必要があります。
1)バージョン2.4
からバージョン2.6
に切り替える必要があります。 2.2
から2.6
への2.2
は機能せず、下位互換性がないため、段階的に更新する必要があります。
実際、更新自体:
apt-get update apt-get install mongodb-org
2) 2.6
アップグレードした後、 admin
データベースに移動して、ドキュメントの互換性をチェックするいくつかのコマンドを実行する必要があります。
use admin db.upgradeCheckAllDBs()
3) mongodb
バージョン2.6
以降、既に述べたように、読み取り、書き込みなどのコレクションまでの役割分mongodb
およびユーザーの設定権限が出現したため、これらの役割を適宜設定する必要があります。そうしないと、 auth
コマンドを実行できません。 。
db.auth('admin','password')
これを行うには、まずadmin
データベースに「管理者」ユーザーを作成します
db.createUser({user:"admin", pwd:"passwd", roles:[{role:"userAdminAnyDatabase", db:"admin"}]})
4)その後、目的のベースに移動します。このベースで作業を行い、接続します。そこにユーザーを作成します。
use newdb db.createUser({user:"admin", pwd:"passwd", roles:[{role:"dbAdmin", db:"newdb"}]})
system.users
コレクションのadmin
データベースにレコードが自動的に作成されます
次のコマンドでデータベースユーザーを表示できます。
db.runCommand( { usersInfo: [ { user: "admin", db: "newdb" } ], showPrivileges: true } )
まあ、このすべての後、オーバーロードすることを忘れないでください。
service mongod restart
このバージョンのubuntu
では、サービスはmongodb
なくmongod
と呼ばれ、 /etc
の設定はmongod.conf
と呼ばれます。これは、アップグレード中に混乱しないように下位互換性がないためです。
2.6から3.0バージョン
新しいバージョン3.0
とストレージエンジンの革新的な変更については、すでに多くのことが書かれています。繰り返しません。
3.0
アップグレードする前に3.0
バージョン2.6
にジャンプせずに順次アップグレードすることをお勧めします。 それは2.2->2.4->2.6
です。
最新バージョンは2.6.5
以上を推奨します。
ubuntu
のインストール自体ubuntu
かなり標準です
3番目のバージョンのリポジトリを追加します。
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10 echo "deb http://repo.mongodb.org/apt/ubuntu "$(lsb_release -sc)"/mongodb-org/3.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.0.list
Ubuntu 15.04
echo "deb http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.0.list
インストール:
apt-get update apt-get install -y mongodb-org
各コンポーネントについて、インストール中にバージョンを示します。
apt-get install -y mongodb-org=3.0.2 mongodb-org-server=3.0.2 mongodb-org-shell=3.0.2 mongodb-org-mongos=3.0.2 mongodb-org-tools=3.0.2
その後:
service mongod stop service mongod start
mongodb
のバージョンを見てみましょmongodb
。
root@user-pc:~# mongo MongoDB shell version: 3.0.2 connecting to: test > db.version() 3.0.2 >
バージョン3
場合、すべてがうまくいったので、ストレージを変更できます。 デフォルトはMMAPv1
です。
/etc/mongo.conf
変更する/etc/mongo.conf
は、オプションを追加します。
storageEngine = wiredTiger
新しいリポジトリに関連する可能なオプションの詳細については、 こちらをご覧ください。
そして、 /var/lib/mongodb
空になるようにします。そうしないと、 mongodb
は自然に起動しません。その前に、すべてのデータベースに対してmongodump
を実行する必要があります
service mongod restart
ストレージのエンジンのバージョンを確認します。
root@user-pc:/etc# mongo MongoDB shell version: 3.0.2 connecting to: test > db.serverStatus()
もしstorageEngine
ならすべてがstorageEngine
あればwiredTiger
を探しています。
"storageEngine" : { "name" : "wiredTiger" }
ここで、 admin
を含むデータベースをインポートする必要があります
mongorestore --port 27017 -d admin
PyMongoの新機能
データベースの新しいバージョンと一緒に、 Python
PyMongo
用の新しいバージョンのドライバーPyMongo
、いくつかの古いメソッドが削除されました:
pip install -U pymongo
データベース自体を更新しなくても、すべてが以前のように機能するわけではありません。 すぐに気づいたことから:
- ユニバーサル化と統一のために、メソッド
update_one, insert_many, find_one_and_delete
仕様にupdate_one, insert_many, find_one_and_delete
ました - また、統合のために、
MongoClient
データベースに残されたコネクタは1つだけであり、MongoClient
から'slave_okay': True
などのオプション'slave_okay': True
削除されました。ReplicaSetConnection
とMasterSlaveConnection
削除されました。MongoReplicaSetClient
、互換性のためにしばらくの間残されています。
使用例:
>>> # Connect to one standalone, mongos, or replica set member. >>> client = MongoClient('mongodb://server') >>> >>> # Connect to a replica set. >>> client = MongoClient('mongodb://member1,member2/?replicaSet=my_rs') >>> >>> # Load-balance among mongoses. >>> client = MongoClient('mongodb://mongos1,mongos2')
-
copy_database
メソッドを削除 -
end_request()
メソッドはend_request()
さend_request()
代わりにclose()
を使用することをお勧めします。 - コミュニティの一部は、
asyncio
からの非同期プログラミングとasyncio
ネイティブサポートがあることを期待していましたが、残念ながら残念です。asyncio
用の優れたモータードライバーがありますが、残念ながら、asyncio
用には、実験的なasyncio-mongoドライバーのみが不十分に開発されており、GridFS
サポートがありませGridFS
集計フレームワークでは、カーソルは
result
ではなくすぐに返されるように
result
。
比較クエリと論理クエリ
$eq
比較演算子
$eq
db.test.find({ field: <value> })
同等です
{ _id: 1, item: { name: "ab", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] } { _id: 2, item: { name: "cd", code: "123" }, qty: 20, tags: [ "B" ] } db.test.find( { qty: { $eq: 20 } } ) # db.test.find( { qty: 20 } ) db.test.find( { tags: { $eq: [ "A", "B" ] } } ) # : db.test.find( { tags: [ "A", "B" ] } )
$ gt以上
$gt
は、フィールド値が指定された値より大きい(>)
文書を選択します。
db.test.find( { qty: { $gt: 10 } } )
$ gteは以上
$gte
は、フィールドの値が指定された値以上(>=)
ドキュメントを選択します。
db.test.find( { qty: { $gte: 10 } } )
$ ltより小さい
$lt
は、フィールドの値が指定した(<)
より小さいドキュメントを選択(<)
ます
db.test.find( { qty: { $lt: 10 } } )
$ lte以下
$lte
は、フィールド値が指定した値以下(<=)
ドキュメントを選択(<=)
ます
db.test.find( { qty: { $lte: 10 } } )
売り手の利益が100
未満の場合、プレミアムは無効です。
db.test.update({ "vendor.profit": { $lte: 100 } }, { $set: { premium: 0 } })
$ neは等しくありません
$ne
は、フィールド値が指定された値と等しくない(! =)
文書を選択します。
db.test.find( { qty: { $ne: 10 } } )
エントリーチェックで$
{ _id: 1, qty: 10, tags: [ "name", "lastname" ], } db.test.find({ tags: { $in: ["name", "lastname"] } } )
正規表現の例
db.test.find( { tags: { $in: [ /^be/, /^st/ ] } } )
$ nin非エントリチェック
$in
同じ$in
が、逆も同様で、配列に値が欠落していることを確認します。
db.test.find( { qty: { $nin: [ 5, 15 ] } } )
$または演算子または
古典的な演算子
はいくつかの値を取り、それらの少なくとも1つが条件に一致することを確認します。
db.test.find( { $or: [ { quantity: { $lt: 10 } }, { price: 10 } ] } )
このクエリでは、2つのインデックスをコンパイルすることが提案されています。
db.test.createIndex( { quantity: 1 } ) db.test.createIndex( { price: 1 } )
フルテキスト検索で$or
$text
演算子と組み合わせて使用する場合、インデックスが必要です。
$および演算子「and」
オペレーターは、検索された文書内にリストされているすべての値の存在
チェックします。
db.test.find( { $and: [ { price:10 }, { check: true } } ]
$or
次の例
db.test.find( { $and : [ { $or : [ { price : 50 }, { price : 80 } ] }, { $or : [ { sale : true }, { qty : { $lt : 20 } } ] } ] } )
否定演算子ではない
選択内の条件に一致するドキュメントがないことを確認します。
db.test.find( { price: { $not: { $gt: 10 } } } )
正規表現の例:
import re for no_docs in db.test.find( { "item": { "$not": re.compile("^p.*") } } ): print no_docs
$または演算子not or
db.test.find( { $nor: [ { price: 10 }, { qty: { $lt: 20 } }, { sale: true } ] } )
テストコレクション内のこのクエリは、次のドキュメントを検索します。
- 価格フィールドの値が10ではありません
- qtyフィールドの値は少なくとも20です
- 「sale」の値は「true」ではありません
$はフィールドの存在をチェックして存在します
$exists
は、特定のキーが存在するか存在しないドキュメントを取得します。
パラメータfalse
として$exists
を指定$exists
と、リクエストはqty
キーが定義されていないドキュメントを返します。
db.test.find( { qty: { $exists: true } } )
$タイプBSON
タイプチェック
db.test.find( { field: { $type: -1 } } );
種類 | 数 | 注釈 |
ダブル | 1 | |
ひも | 2 | |
対象 | 3 | |
配列 | 4 | |
バイナリデータ | 5 | |
未定義 | 6 | 非推奨。 |
オブジェクトID | 7 | |
ブール値 | 8 | |
日付 | 9 | |
ヌル | 10 | |
正規表現 | 11 | |
Javascript | 13 | |
記号 | 14 | |
JavaScript(スコープ付き) | 15 | |
32ビット整数 | 16 | |
タイムスタンプ | 17 | |
64ビット整数 | 18 | |
最小キー | 255 | -1を使用したクエリ。 |
最大キー | 127 |
$ mod
$mod
演算子は、値が最初の引数で除算され、除算の残りが2番目の引数に等しいフィールドを選択するために使用されます。
たとえば、ドキュメントがあります:
{ "_id" : 1, "item" : "aa123", "qty" : 0 } { "_id" : 2, "item" : "bb123", "qty" : 7 } { "_id" : 3, "item" : "cc123", "qty" : 15 }
リクエスト:
db.test.find( { qty: { $mod: [ 5, 0 ] } } )
次のドキュメントを返します。
{ "_id" : 1, "item" : "aa123", "qty" : 0 } { "_id" : 3, "item" : "cc123", "qty" : 15 }
SQL
からのアナログ
select * from t where qty % 5 = 0;
C 2.6
バージョンでは、1つの要素のみを転送することは禁じられており、エラーが返されます。 また、3つ以上の引数を渡すと、エラーも生成されます。以前のバージョンでは、余分な引数は単に無視されていました。
すべて選択すべて一致
配列の複数の要素を作成します。
db.test.find( { tags: { $all: [ "python", "mongodb", "javascript" ] } } )
$ elemMatch
同じサブドキュメントに属する2つ以上の属性を比較する必要がある場合に使用します。
配列内にすべての条件に一致する要素があることを確認します。
{ _id: 1, results: [ 82, 85, 88 ] } { _id: 2, results: [ 75, 88, 89 ] } db.test.find( { results: { $elemMatch: { $gte: 80, $lt: 85 } } } )
結果が得られます。
{ _id: 1, results: [ 82, 85, 88 ] }
別の例:
{ _id: 1, results: [{ product: "abc", score: 10 }, { product: "xyz", score: 5}] } { _id: 2, results: [{ product: "abc", score: 8 }, { product: "xyz", score: 7}] } { _id: 3, results: [{ product: "abc", score: 7 }, { product: "xyz", score: 8}] } >db.test.find( { results: { $elemMatch: { product: "xyz", score: { $gte: 8 } } } } ) { "_id": 3, "results": [{ "product": "abc", "score": 7 }, { "product": "xyz", "score": 8 } ] }
配列の長さによる$サイズの検索
$size
演算子は、配列内の要素の数が$size
値に等しいドキュメントを検索します。 たとえば、laguages配列に2つの要素があるすべてのドキュメントを抽出します。
db.persons.find ({languages: {$size:2}})
このようなリクエストは、たとえば次のドキュメントに対応します。
{"name": "Alex", "age": "32", languages: ["python", "mongodb"]}
$位置演算子
$
はさまざまな場合に使用できます。 配列の値がどのインデックスの下にあるのかわからないが、それを使用したい場合は、「位置演算子」を使用します
たとえば、ドキュメントがあります:
{ "_id" : 3, "semester" : 1, "grades" : [ 85, 100, 90 ] } { "_id" : 4, "semester" : 2, "grades" : [ 79, 85, 80 ] }
そして、それらを検索した後、ドキュメント全体ではなく、クエリに対応する1つの値のみが表示されるようにしますが、事前にどの値が存在するかはわかりません。
>db.test.find( { semester: 1, grades: { $gte: 85 } }, { "grades.$": 1 } ) { "_id" : 3, "grades" : [ 85 ] }
更新の例:
db.test.update( { _id: 22 } , { $set: { "array.$.name" : "alex" } } )
$スライスは範囲を見つける
$slice
配列に保存されている値の範囲を検索します。
最初の10個のイベントを見つけます。
db.test.find( { }, { "events" : { $slice: 10 } } )
過去10件のイベントを検索:
db.test.find( { }, { "events" : { $slice: -10 } } )
Mongodb、正規表現、インデックスなどでの全文検索
Habréには、mongodb`の
優れた出版物がありましたが、それ以来、新しい演算子と新しい機能が追加されました。
テキスト検索はインデックスなしでは機能しないため、それらについて説明しましょう。
任意のテキストフィールドまたは配列に対して単純なインデックスが作成されます。
db.test.createIndex( { title: "text", content: "text" } )
フィールド名またはワイルドカード修飾子を使用できます。
db.text.createIndex( { "$**": "text" } )
全文検索用のインデックスを作成する場合、英語でない場合は言語を考慮する必要があります。
db.test.createIndex( { content : "text" }, { default_language: "russian" } )
バージョン2.6
以降、多くの言語のテキストインデックスを一度に設定できるようになりました。
- ダまたはデンマーク語
- nlまたはオランダ語
- enまたは英語
- fiまたはフィンランド語
- frまたはフランス語
- デまたはドイツ語
- 胡またはハンガリー人
- それまたはイタリア語
- nbまたはノルウェー語
- ptまたはポルトガル語
- roまたはルーマニア語
- ruまたはロシア語
- esまたはスペイン語
- svまたはスウェーデン語
- trまたはトルコ語
MongoDB
は、インデックスの作成時にドキュメントで指定された言語を使用します。 ドキュメントで指定された言語は、デフォルトの言語をオーバーライドします。 埋め込みドキュメントの言語は、インデックスの他のすべてをオーバーライドします。
{ _id: 1, language: "portuguese", original: "A sorte protege os audazes.", translation: [ { language: "english", quote: "Fortune favors the bold." }, { language: "russian", quote: " ." } ] }
また、 language_override
パラメーターを使用してlanguage_override
フィールドを指定することもできます。
たとえば、ドキュメントの場合:
{ _id: 2, idioma: "english", quote: "Fortune favors the bold." } { _id: 3, idioma: "russian", quote: " ." }
インデックスは次のようになります。
db.text.createIndex( { quote : "text" }, { language_override: "idioma" } )
インデックスには、たとえば次のような特別な名前{ name: "name" }
割り当てることができます。
db.text.createIndex( { content: "text", "users.title": "text" }, { name: "text_Index" } )
この名前は、インデックスの削除に使用すると便利です。
db.text.dropIndex("text_Index")
また、テキストインデックスの場合、検索するフィールドの重要度、重みを設定できます。
たとえば、次のフィールドに重みを設定します: content - 10
、 keywords - 5
、およびtitle - 1
。
db.test.createIndex( { content: "text", tags: "text", title: "text" }, { weights: { content: 10, tags: 5, }, name: "TextIndex"} )
インデックスを使用して、出力のレコード数を制限できます。
{ _id: 1, dept: "one", content: "red" } { _id: 3, dept: "one", content: "red" } { _id: 2, dept: "two", content: "gren" } db.test.createIndex( { dept: 1, content: "text" } ) db.test.find( { dept: "one", $text: { $search: "green" } } )
インデックスに制限があるため、出力は2つではなく1つのドキュメントになります。
Python
サンプルインデックス:
#PyMongo db.text.ensure_index( [ ('descr', "text" ), ( 'title.ru', "text" ) ], default_language="russian", name="full_text")
テキスト検索
mongodbでテキスト検索が表示された直後に、runCommandを使用して実行されました。次に例を示します。
db.collection.runCommand( "text", { search: "" } )
ただし、バージョン2.6
以降、新しい演算子$ text
単一単語検索:
db.articles.find( { $text: { $search: "coffee" } } )
複数単語検索:
db.articles.find( { $text: { $search: "bake coffee cake" } } )
フレーズで検索:
db.articles.find( { $text: { $search: "\"coffee cake\"" } } )
検索からフィールドを除外-
db.articles.find( { $text: { $search: "bake coffee -cake" } } )
また、 mongodb 2.6
では、別の$メタ演算子が表示され、リクエストと一致する結果の精度が示されました。
db.text.insert([ { "_id": 4, "descr" : " " }, { "_id": 3, "descr" : " -" }, { "_id":6, "descr" : " " }, { "_id":7, "descr" : " " }, { "_id":8, "descr" : " " }, { "_id":9, "descr" : ", " }, { "_id":10, "descr" : ", " }, { "_id":11, "descr" : " " } { "_id":12, "descr" : " " }, { "_id":13, "descr" : " " }, ]) db.text.createIndex( { descr : "text" }, { default_language: "russian" } ) db.text.find( { $text: { $search: "" } }, { score: { $meta: "textScore" } }).sort( { score: { $meta: "textScore" } } ) { "_id" : 13, "descr" : " ", "score" : 0.75 } { "_id" : 4, "descr" : " ", "score" : 0.6666666666666666 } { "_id" : 6, "descr" : " ", "score" : 0.6666666666666666 } { "_id" : 12, "descr" : " ", "score" : 0.6666666666666666 }
ここで{ score: { $meta: "textScore" } }
結果に含まれる値に新しいフィールドを作成し、それが既にソートに関与しています。
$ regexを検索
MongoDB
はPerl
互換の正規表現を使用します。
db.test.insert([ { "_id" : 1, "descr" : "abc123" }, { "_id" : 2, "descr" : "abc123" }, { "_id" : 3, "descr" : "eee789" } ]) db.test.find( { sku: { $regex: /^ABC/i } } ) { "_id" : 1, "sku" : "abc123", "description" : "Single line description." } { "_id" : 2, "sku" : "abc123", "description" : "Single line description." }
i
大文字と小文字を区別しません。
PostgreSQL
アナログ
select title from article where title ~ '^a' 'abc'
原子演算子(データの変更)
通常、これらの修飾子はすべて、 db.test.update()
およびdb.test.findAndModify()
更新操作に使用されます
$ inc increment
指定された値だけフィールドを増減します。
db.test.update( { _id: 1 }, { $inc: { qty: -2, "orders": 1 } } )
$乗数の増分
フィールド値に指定された値を乗算します。
{ _id: 5, item: "mac", price: 10 } db.test.update({ _id: 1 }, { $mul: { price: 2 } } ) { _id: 5, item: "mac", price : 20 }
$名前フィールドの名前変更
{ "_id": 1, "name": "alex" } db.test.update( { _id: 1 }, { $rename: { 'name': 'alias'} } ) { "_id": 1, "alias": "alex" }
$ setはフィールドの値を変更します
これはおそらくupdate
使用される主な変更演算子です。 多くの場合、mongodbのコンテキストでの単純なトランザクションとして記憶されます。
db.test.save({ "_id":8, "qty":"", tags:"" }) db.test.update( { _id: 8 }, { $set: { qty: 100, tags: [ "linux", "ubuntu"] } }) { "_id" : 8, "qty" : 100, "tags" : [ "linux", "ubuntu" ] }
$ setOnInsertは、新しいドキュメントにフィールドを追加します
update
3番目の引数は、オプション{ upsert: true }
これは、変更のドキュメントが見つからなかった場合、新しいドキュメントを作成することを意味します。 また、 $setOnInsert
オプションは、そこに挿入するフィールドを$setOnInsert
ます。
>db.test.update( { _id: 7 }, { $set: { item: "windows" }, $setOnInsert: { os: 'bad' } }, { upsert: true } ) { "_id" : 7, "item" : "windows", "os" : "bad" }
$set
を実行するフィールドは、新しく作成されたドキュメントにも表示されます。
$ unsetはキーを削除します
{ "_id" : 8, "qty" : 100, "tags" : [ "linux", "ubuntu" ] } db.test.update( { _id: 8 }, { $unset: { qty: "", tags: "" } } ) { "_id" : 8 }
最小の場合、最小更新
$min
はフィールドを更新します。指定された値がフィールドの現在の値より小さい場合、 $min
は異なるタイプの値を比較できます。
> db.test.save({ _id: 9, high: 800, low: 200 }) > db.test.update( { _id:9 }, { $min: { low: 150 } } ) >db.test.findOne({_id:9}) { "_id" : 9, "high" : 800, "low" : 150 }
$ maxアップデート
$max
は、指定された値がフィールドの現在の値より大きい場合にフィールドを更新します。
> db.test.save({ _id: 9, high: 800, low: 200 }) > db.test.update( { _id:9 }, { $max: { high: 900 } } ) > db.test.findOne({_id:9}) { "_id" : 9, "high" : 900, "low" : 200 }
$ currentDateは現在の日付を設定します
フィールドの値を現在の日付に設定します。
> db.test.save({ _id:11, status: "init", date: ISODate("2015-05-05T01:11:11.111Z") }) > db.test.update( { _id:12 }, { $currentDate: { date: true } } ) > db.test.findOne({_id:12}) { "_id" : 12, "status" : "a", "date" : ISODate("2015-05-10T21:07:31.138Z") }
配列の変更
$ addToSetが値を追加しない場合
配列に値がまだない場合は値を追加し、値がある場合は何もしません。
db.test.save({ _id:1, array: ["a", "b"] }) db.test.update( { _id: 1 }, { $addToSet: {array: [ "c", "d" ] } } ) { "_id" : 1, "array" : [ "a", "b", [ "c", "d" ] ] } db.test.update( { _id: 1 }, { $addToSet: {array: "e" } } ) { "_id" : 1, "array" : [ "a", "b", [ "c", "d" ], "e" ] }
$ popは最初または最後を削除します
配列の最初または最後の要素を削除します。 -1が指定されている場合、最初の要素が削除され、1が指定されている場合、最後の要素が削除されます。
> db.test.save({ _id: 1, scores: [ 6, 7, 8, 9, 10 ] }) { "_id" : 1, "scores" : [ 6, 7, 8, 9, 10 ] } > db.test.update( { _id: 1 }, { $pop: { scores: -1 } } ) > db.test.findOne({_id:1}) { "_id" : 1, "scores" : [ 7, 8, 9, 10 ] } > db.test.update( { _id: 1 }, { $pop: { scores: 1 } } ) > db.test.findOne({_id:1}) { "_id" : 1, "scores" : [ 7, 8, 9 ] }
$ pullAllは、指定されたすべてを削除します
指定されたすべての要素を配列から削除します。
{ _id: 1, scores: [ 0, 2, 5, 5, 1, 0 ] } db.test.update( { _id: 1 }, { $pullAll: { scores: [ 0, 5 ] } } ) { "_id" : 1, "scores" : [ 2, 1 ] }
要求に応じて$プル削除
{ _id: 1, votes: [ 3, 5, 6, 7, 7, 8 ] } > db.test.update( { _id: 1 }, { $pull: { votes: { $gte: 6 } } } ) { _id: 1, votes: [ 3, 5 ] }
$ pushは値を追加します
配列に値を追加します。
db.test.update( { _id: 1 }, { $push: { scores: 100} } )
$pushAll
$ pushの修飾子
一度にたくさん
リストされた各アイテムを配列に追加します。
たとえば、これを行う場合: { $push: { scores: [ 2, 10 ] } }
その場合、出力は次のような配列になります: "scores" : [7, 8, 9, 90, 92, 85, [ 2, 10 ] ]
つまり、配列である要素がもう1つ追加されます。
そして、 $each
を介して、リストの各要素が配列の要素として追加される場合:
> db.test.update( { _id: 1 }, { $push: {scores: { $each: [ 90, 92, 85 ] } } } ) {"_id" : 1, "scores" : [7, 8, 9, 90, 92, 85, 2, 10 ] }
$ pushを使用する場合、$スライスはアイテム数を制限します
$push
貼り付けるときに配列要素の数を制限します。 必然的に$each
を使用します$each
それなしで使用しようとすると、エラーが返されます。
{ "_id" : 1, "scores" : [ 10, 20, 30 ] } > db.test.update( { _id: 1 }, { $push: { scores: { $each: [50, 60, 70], $slice: -5 } } } ) { "_id" : 1, "scores" : [ 20, 30, 50, 60, 70 ] }
$slice
は20
の最初の要素を切り取ります。 -5
なく5
指定した場合、最後の要素70
返されます。
$ sort sort配列要素
指定されたフィールドに従って配列の要素をソートします。 $each
演算子$each
を使用することも必須です。 挿入せずに並べ替える必要がある場合は、 $each
を空白のままにすることができます。
{ "_id" : 2, "tests" : [ 80, 70, 80, 50 ] } > db.test.update( { _id: 2 }, { $push: { tests: { $each: [40, 60], $sort: 1 } } }) { "_id" : 2, "tests" : [ 40, 50, 60, 70, 80, 80 ] }
別の例:
db.test.update( { _id: 1 }, { $push: { field: { $each: [ ], $sort: { score: 1 } } } }) { "_id" : 1, "field" : [ { "id" : 3, "score" : 5 }, { "id" : 2, "score" : 6 }, { "id" : 1, "score" : 7 }, ] }
$位置は挿入位置を示します
値を挿入する配列要素のカウントを示します。
{ "_id" : 1, "scores" : [ 100 ] } db.test.update({ _id: 1 }, {$push: { scores: { $each: [50, 60, 70], $position: 0 } } }) { "_id" : 1, "scores" : [ 50, 60, 70, 100 ] }
$ビットはビットごとに更新されます
ビット単位のフィールド更新を実行します。 演算子はビット単位のand
、 or
およびxor
サポートします。
{ "_id" : 1, "expdata" : 13 } > db.bit.update({_id:1}, {$bit:{expdata:{and:NumberInt(10)} } } ) { "_id" : 1, "expdata" : 8 }
$分離-霧化
たとえば、更新操作が行われている間、ドキュメントを読み取りおよび書き込み用にロックします。
削除時に$isolated
れた$isolated
使用:
db.test.remove( { temp: { $lt: 10 }, $isolated: 1 } )
更新時に$isolated
た$isolated
を使用:
db.test.update( {status: "init" , $isolated: 1 }, { $inc: { count : 1 }}, {multi: true } )
$分離は、シャードクラスターでは機能しません
バージョン2.2
: $isolated
演算子が$atomic
置き換わりました
mongodbのトランザクション、一意のインデックス、2フェーズコミットについて
当然、 MongoDB
PostgreeSQL
ような従来のSQL
ソリューションのようなPostgreeSQL
はそうではなく、おそらく不可能です。 もしそうなら、それはむしろ、完全な正規化と整合性制御を備えたリレーショナルデータベースになります。
したがって、 mongoDB
トランザクションについて説明する場合、原則として、 update()
およびfindAndModify()
で一意のインデックスと組み合わせて使用されるタイプ$set
アトミック操作を意味します。 複数のデータベース内でトランザクションを確保する必要がある場合、リレーショナルデータベースで一般的な2フェーズコミットも同様です。
一意のインデックス
mongodb
の一意のインデックスにより、インデックスフィールドの重複値を含むすべてのドキュメントが拒否されます。
db.test.createIndex( { "user_id": 1 }, { unique: true } )
コレクションがありますNik
と呼びましょう。このコレクションには、 name
フィールドの値がNik
ドキュメントはありません。 複数のクライアントが{ upsert: true }
パラメーターを使用してこのドキュメントを同時に更新しようとしていると仮定します(条件によって、更新するドキュメントが存在しない場合、作成する必要があることを意味します)。
例:
db.test.update( { name: "Nik" }, { name: "Nik", vote: 1 }, { upsert: true } )
update()
, , , .
, . . , .
unique
false
MongoDB
, A
B
.
:
- `accounts` .
- `transactions` , .
accounts transactions
accounts
db.accounts.insert( [ { _id: "A", balance: 1000, pendingTransactions: [] }, { _id: "B", balance: 1000, pendingTransactions: [] } ] )
transactions
.
db.transactions.insert({ _id: 1, source: "A", destination: "B", value: 100, state: "initial", lastModified: new Date()})
:
-
source
destination
. -
value
, . -
state
.initial
,pending
,applied
,done
,canceling
,canceled
. -
lastModified
.
1)
, initial
. t
> var t = db.transactions.findOne( { state: "initial" } ) > t { "_id" : 1, "source" : "A", "destination" : "B", "value" : 100, "state" : "initial", "lastModified" : ISODate("2015-05-26T16:35:54.637Z") }
2) pending
initial
pending
.
> db.transactions.update( { _id: t._id, state: "initial" }, { $set: { state: "pending" }, $currentDate: { lastModified: true } } ) > db.transactions.find() { "_id" : 1, "source" : "A", "destination" : "B", "value" : 100, "state" : "pending", "lastModified" : ISODate("2015-05-26T17:02:19.002Z") } >
3)
, , value
, pendingTransactions
_id
( ).
> db.accounts.update( { _id: t.source, pendingTransactions: { $ne: t._id } }, { $inc: { balance: -t.value }, $push: { pendingTransactions: t._id } } ) > db.accounts.update( { _id: t.destination, pendingTransactions: { $ne: t._id } }, { $inc: { balance: t.value }, $push: { pendingTransactions: t._id } } ) > db.accounts.find() { "_id" : "A", "balance" : 900, "pendingTransactions" : [ 1 ] } { "_id" : "B", "balance" : 1100, "pendingTransactions" : [ 1 ] }
4) applied
.
> db.transactions.update( { _id: t._id, state: "pending" }, { $set: { state: "applied" }, $currentDate: { lastModified: true } } ) > db.transactions.find() { "_id" : 1, "source" : "A", "destination" : "B", "value" : 100, "state" : "applied", "lastModified" : ISODate("2015-05-26T17:13:15.517Z") }
5) _id
pendingTransactions
: _id
pendingTransactions
.
> db.accounts.update( { _id: t.source, pendingTransactions: t._id }, { $pull: { pendingTransactions: t._id } } ) > db.accounts.update( { _id: t.destination, pendingTransactions: t._id }, { $pull: { pendingTransactions: t._id } } ) > db.accounts.find() { "_id" : "A", "balance" : 900, "pendingTransactions" : [ ] } { "_id" : "B", "balance" : 1100, "pendingTransactions" : [ ] }
6) done
.
> db.transactions.update( { _id: t._id, state: "applied" }, { $set: { state: "done" }, $currentDate: { lastModified: true } } ) > db.transactions.find() { "_id" : 1, "source" : "A", "destination" : "B", "value" : 100, "state" : "done", "lastModified" : ISODate("2015-05-26T17:22:22.194Z") }
. .
1) canceling
, , canceling
.
db.transactions.update( { _id: t._id, state: "pending" }, {$set: { state: "canceling" }, $currentDate: { lastModified: true }} ) > db.transactions.find() { "_id" : 1, "source" : "A", "destination" : "B", "value" : 100, "state" : "canceling", "lastModified" : ISODate("2015-05-26T18:29:28.018Z") }
2)
.
> db.accounts.update( { _id: t.destination, pendingTransactions: t._id }, { $inc: { balance: -t.value }, $pull: { pendingTransactions: t._id } } ) > db.accounts.update( { _id: t.source, pendingTransactions: t._id }, { $inc: { balance: t.value}, $pull: { pendingTransactions: t._id } } ) > db.accounts.find() { "_id" : "A", "balance" : 1000, "pendingTransactions" : [ 1 ] } { "_id" : "B", "balance" : 1000, "pendingTransactions" : [ 1 ] } >
3) cancelled
.
db.transactions.update( { _id: t._id, state: "canceling" }, { $set: { state: "cancelled" }, $currentDate: { lastModified: true } } ) > db.transactions.find() { "_id" : 1, "source" : "A", "destination" : "B", "value" : 100, "state" : "cancelled", "lastModified" : ISODate("2015-05-26T19:14:11.830Z") }
, . .
findAndModify()
, :
t = db.transactions.findAndModify({ query: { state: "initial", application: { $exists: false } }, update: {$set: { state: "pending", application: "App1"}, $currentDate:{ lastModified: true }}, new: true })
6. JOIN-
JOIN
- mongo
, - . stackoverflow
, , .
, , , , .
- , , { type: 'news' }
.
, , .
, , aggregation framework
. pipeline
. , , , , , ..
, , .
db.test.insert([ { "_id":"gomer", "type":"user", "group":["user", "author"] }, { "_id":"vasya", "type":"user", "group":["user"] } ])
.
db.test.insert([ { "_id": 1, "type": "blogs", "user": "gomer", "article": "aaa" }, { "_id": 2, "type": "blogs", "user": "vasya", "article": "bbb" }, { "_id": 3, "type": "blogs", "user": "gomer", "article": "ccc" } ])
, . , .
, , , "".
users = [doc._id for doc in db.test.find({"type":'user', 'group': {'$all': ['author']}})] articles = db.test.find({"type": "blogs", "user": {'$in': users})
c SQL :
SELECT blogs.* FROM blogs, user, usergroup, group WHERE blogs.user = user.id AND usergroup.user = user.id AND usergroup.group = group.id AND group.name = 'author';
user, d jsonb. — :
SELECT blogs.* FROM blogs, user WHERE blogs.user = user.id AND user.group ? 'author'; SELECT blogs.* FROM (SELECT * FROM test WHERE d->type = 'blogs') blogs, (SELECT * FROM test WHERE d->type = 'user') user WHERE blogs.d->user = user.id AND user.d->group ? 'author';
pipe.
db.test.aggregate([ { $match: { $or: [ {type: "blogs"}, {type: "user"} ] } }, { $project: { a: 1, blogs: { $cond: { if: { type: '$blogs'}, then: {_id:"$_id", user:"$user", article:"$article"}, else: null } }, user: { $cond: { if: { type: '$user' }, then: { _id:"$_id", group:"$group"}, else: null } } } }, { $group : { _id : { a: "$a" }, user: { $push: "$user" }, blog: { $push: "$blogs" }, } }, { $unwind : "$blog" }, { $unwind : "$user" }, { $project:{ user: "$user", article: "$blog", matches: { $eq:[ "$user._id", "$blog.user" ] } } }, { $match: { matches: true } } ])
. 7 .
, mongodb
pipeline
. , , , , , .
SQL Terms, Functions, and Concepts | MongoDB Aggregation Operators |
---|---|
WHERE | $match |
GROUP BY | $group |
HAVING | $match |
SELECT | $project |
ORDER BY | $sort |
LIMIT | $limit |
SUM() | $sum |
COUNT() | $sum |
join | $unwind |
.
> db.ag.aggregate([ { $match: {$or:[{type:"blogs"},{type:"user"}]} } ]) { "_id" : "gomer", "type" : "user", "group" : [ "user", "author" ] } { "_id" : "vasya", "type" : "user", "group" : [ "user" ] } { "_id" : 1, "type" : "blogs", "user" : "gomer", "article" : "aaa" } { "_id" : 2, "type" : "blogs", "user" : "vasya", "article" : "bbb" } { "_id" : 3, "type" : "blogs", "user" : "gomer", "article" : "ccc" }
$match
find()
, , .
c $project
, blogs
users
. 2.6
$cond
. blogs
users
, .
db.test.aggregate([ { $match: {$or:[ { type:"blogs"}, { type: "user"} ] } }, { $project: { a: 1, blogs: { $cond: { if: {type: '$blogs'}, then: {_id:"$_id", user:"$user", article:"$article"}, else: null } }, user: { $cond: { if: { type: '$user'}, then: {_id:"$_id", group:"$group"}, else: null } } } } ]) { "_id": "gomer", "blogs": { "_id" : "gomer" }, "user": { "_id": "gomer", "group": [ "user", "author" ] } } { "_id": "vasya", "blogs": { "_id" : "vasya" }, "user" : { "_id" : "vasya", "group": [ "user" ] } } { "_id": 1, "user": { "_id": 1 }, "blogs" : { "_id": 1, "user": "gomer", "article": "aaa" } } { "_id": 2, "user": { "_id": 2 }, "blogs" : { "_id": 2, "user": "vasya", "article": "bbb" } } { "_id": 3, "user": { "_id": 3 }, "blogs" : { "_id": 3, "user": "gomer", "article": "ccc" } }
:
...{ $group : { _id : { a: "$a" }, user: { $push: "$user" }, blog: { $push: "$blogs" }, } }... { "_id" : { "a" : null }, "user": [ { "_id": "gomer", "group": [ "user", "author" ] }, { "_id": "vasya", "group": [ "user" ] }, { "_id": 1 }, { "_id": 2 }, { "_id": 3 } ], "blog": [ { "_id": "gomer" }, { "_id": "vasya" }, { "_id": 1, "user": "gomer", "article": "aaa" }, { "_id": 2, "user": "vasya", "article": "bbb" }, { "_id": 3, "user": "gomer", "article": "ccc"} ] }
....{ $unwind : "$blog" }, { $unwind : "$user" } .... { "_id": { "a":null }, "user": { "_id": "gomer", "group": [ "user", "author" ] }, "blog": { "_id": "gomer" } } { "_id": { "a":null }, "user": { "_id": "vasya", "group": [ "user" ] }, "blog" : { "_id": "gomer" } } { "_id": { "a":null }, "user": { "_id": 1 }, "blog": { "_id" : "gomer" } } { "_id": { "a" : null }, "user" : { "_id" : 2 }, "blog" : { "_id" : "gomer" } } { "_id": { "a" : null }, "user" : { "_id" : 3 }, "blog" : { "_id" : "gomer" } } { "_id": { "a": null }, "user": { "_id": "gomer", "group" : [ "user", "author" ] }, "blog": { "_id": "vasya"}} { "_id": { "a" : null }, "user" : { "_id" : "vasya", "group" : [ "user" ] }, "blog" : { "_id" : "vasya" } } { "_id": { "a" : null }, "user" : { "_id" : 1 }, "blog" : { "_id" : "vasya" } } { "_id": { "a" : null }, "user" : { "_id" : 2 }, "blog" : { "_id" : "vasya" } } { "_id": { "a" : null }, "user" : { "_id" : 3 }, "blog" : { "_id" : "vasya" } } { "_id": { "a" : null }, "user" : { "_id" : "gomer", "group" : [ "user", "author" ] }, "blog" : { "_id" : 1, "user": "gomer", "article" : "aaa" } } { "_id": { "a" : null }, "user": { "_id" "vasya", "group": [ "user" ] }, "blog": { "_id": 1, "user": "gomer", "article": "aaa" } } { "_id": { "a" : null }, "user" : { "_id" : 1 }, "blog" : { "_id" : 1, "user" : "gomer", "article" : "aaa" } } { "_id" : { "a" : null }, "user" : { "_id" : 2 }, "blog" : { "_id" : 1, "user" : "gomer", "article" : "aaa" } } { "_id": { "a" : null }, "user" : { "_id" : 3 }, "blog" : { "_id" : 1, "user" : "gomer", "article" : "aaa" } } { "_id": { "a" : null }, "user" : { "_id" : "gomer", "group" : [ "user", "author" ] }, "blog" : { "_id" : 2, "user": "vasya", "article" : "bbb" } } { "_id": { "a" : null }, "user" : { "_id" : "vasya", "group" : [ "user" ] }, "blog" : { "_id" : 2, "user" : "vasya", "article" : "bbb" } } { "_id": { "a" : null }, "user" : { "_id" : 1 }, "blog" : { "_id" : 2, "user" : "vasya", "article" : "bbb" } } { "_id": { "a" : null }, "user" : { "_id" : 2 }, "blog" : { "_id" : 2, "user" : "vasya", "article" : "bbb" } } { "_id": { "a" : null }, "user" : { "_id" : 3 }, "blog" : { "_id" : 2, "user" : "vasya", "article" : "bbb" } }
, $eq:[ "$user._id", "$blog.user" ]
"user" : { "_id" : 2 }
"blog" : { "user" : "vasya" }
.
...{ $project:{ user:"$user", article:"$blog", matches:{ $eq:[ "$user._id", "$blog.user" ] } } } .....
{ "_id" : { "a" : null }, "user" : { "_id" : 1 }, "article" : { "_id" : 1, "user" : "gomer", "article" : "aaa" }, "matches" : false } { "_id" : { "a" : null }, "user" : { "_id" : 2 }, "article" : { "_id" : 1, "user" : "gomer", "article" : "aaa" }, "matches" : false } { "_id" : { "a" : null }, "user" : { "_id" : 3 }, "article" : { "_id" : 1, "user" : "gomer", "article" : "aaa" }, "matches" : false } { "_id" : { "a" : null }, "user" : { "_id" : "gomer", "group" : [ "user", "author" ] }, "article" : { "_id" : 2, "user" : "vasya", "article" : "bbb" }, "matches" : false } { "_id" : { "a" : null }, "user" : { "_id" : "vasya", "group" : [ "user" ] }, "article" : { "_id" : 2, "user" : "vasya", "article" : "bbb" }, "matches" : true } { "_id" : { "a" : null }, "user" : { "_id" : 1 }, "article" : { "_id" : 2, "user" : "vasya", "article" : "bbb" }, "matches" : false } { "_id" : { "a" : null }, "user" : { "_id" : 2 }, "article" : { "_id" : 2, "user" : "vasya", "article" : "bbb" }, "matches" : false } { "_id" : { "a" : null }, "user" : { "_id" : 3 }, "article" : { "_id" : 2, "user" : "vasya", "article" : "bbb" }, "matches" : false } Type "it" for more
:
{ $match: { matches:true } }
{ "_id": { "a": null }, "user": { "_id": "gomer", "group": [ "user", "author" ] }, "article": { "_id": 1, "user": "gomer", "article": "aaa" }, "matches": true }
{ "_id": { "a": null }, "user": { "_id": "vasya", "group": [ "user" ] }, "article": { "_id": 2, "user": "vasya", "article": "bbb" }, "matches": true }
{ "_id": { "a": null }, "user": { "_id": "gomer", "group": [ "user", "author" ] }, "article": { "_id": 3, "user": "gomer", "article": "ccc" }, "matches": true }
, .
, .
, pipeline
.
7.
, , . :
- , .
- , .
, Mongodb
, — . , , , .
.
:
{ _id:1, type:"blog", title:{ru:"O MongoDB", en:""}, comments: [ { _id: 1, title: "one", "user": "Alex", parent: "root", child: [2, 3]}, { _id: 2, title: "two", "user": "Serg", parent: 1 }, { _id: 3, title: "two", "user": "Andrey", parent: 1 } ] }
:
{ _id: 1, type: "comment", title: "one", "user": "Alex", parent: "root", child: [ 2, 3 ] }, { _id: 2, type: "comment", title: "two", "user": "Serg", parent: 1 }, { _id: 3, type: "comment", title: "two", "user": "Andrey", parent: 1 }
.
, .
, , "" .
.
:
db.test.update( { _id: 1 }, { $pull: { child: 2 } } ) db.test.update( { _id: 1 }, { $pullAll: { child: [ 2, 3 ] } } )
:
db.test.update( { _id: 1 }, { $push: { child: 2 } } } ) db.test.update( { _id: 1 }, { $push: { child: { $each: [ 2, 3 ] } } } )
:
def getTree(docs): tree = { doc["_id"]: doc for doc in docs } for doc in docs: doc['child'] = [] for doc in docs: parent = doc["parent"] if parent != "root": tree[parent]["child"].append(doc) docs={"_id": "root", "child": [doc for doc in docs if doc['parent'] == "root" ]} return docs { _id: 1, type: "comment", title: "one", "user": "Alex", parent: "root", child: [ { _id: 2, type: "comment", title: "two", "user": "Serg", parent: 1 }, { _id: 3, type: "comment", title: "two", "user": "Andrey", parent: 1 } ] }
, , , _id
:
def count(cls): db = connect() ctr = db.test.find({'type':'goods', 'class':cls}).count() childs = db.test.find_one({'_id':cls}) for res in childs['child']: ctr += count(res) return ctr
, _id
, :
def path( id ): p = [] parent = db.test.find_one( {"_id": id }, { "parent": 1, "alias":1, "title":1}) else: path.append( ( parent['alias'], parent['title'] ) ) p += path( parent['parent'] ) return p print ( path("123") ) >>>[ ("one", " "), ("two", " ") ]
,
, { tags : { ru: ", " } }
, . { tags : [ "", "" ] }
.
, .
, , , :
{ _id: 1, title: " ", tags: [ "php", "python" ] } db.test.find({ tags: { $in: ["php", "python" ] } } )
:
- , , `python, javascript`.
- , , , , «».
- , , , .
- .
- , .
- , , , , 5 .
- , `+2` .
- .
- `10` .
- , , ( ).
dt = ( datetime.today() + timedelta( days = -5 ) ) db.test.aggregate([ { $match: { // type: "news", date: { $gt: dt }, // . vate: { $gte: 2 }, // . user: { $in: [ "alex", "pavel" ] } $and: [ // . { pub: true }, { accept: true }, // . { tags: { $in: ["php", "python" ] } } , // . { tags: { $nin: [""] } } ] }, // . { $sort: {'primary': -1, view: -1}}, // , 5 { $limit:3}, // 1 , . { $group: { '_id':'$user', 'id': {'$first':'$_id'}, 'type':{'$first':'$type'}, 'title': {'$first':'$title'}, 'content':{'$first':'$content'}, 'count':{'$first':'$count_comm'}, 'last_comm':{'$first':'$last_comm'}, 'vote':{'$first':'$vote'}, 'tags':{'$first':'$tags'} } }, // . { $project :{ '_id':'$id', 'title':1, 'content':1, 'type':1, 'count':1, 'last_comm':1, 'tags':1, 'vote':1 } } ])
db.test.aggregate([ { $match: { type: "news", date: { $gt: dt }, vate: { $gte: 2 }, user: { $in: [ "alex", "pavel" ] } $and: [ { pub: true }, { accept: true }, { tags: { $in: ["php", "python" ] } } , { tags: { $nin: [""] } } ] }, { $sort: {'primary': -1, view: -1}}, { $limit:3}, { $group: {'_id':'$user', 'id': {'$first':'$_id'}, 'type':{'$first':'$type'}, 'title': {'$first':'$title'}, 'content':{'$first':'$content'}, 'count':{'$first':'$count_comm'}, 'last_comm':{'$first':'$last_comm'}, 'vote':{'$first':'$vote'}, 'tags':{'$first':'$tags'} } }, { $project :{ '_id':'$id', 'title':1, 'content':1, 'type':1, 'count':1, 'last_comm':1, 'tags':1, 'vote':1 } } ])
, — .
-commerce Mongodb
, - — - . , , , , , , .
, - , . .
, , , -.
- ( )
- .
, , , — . , , .
().
:
- , .
- .
, , . :
cursor = db.test.find({ "type": "filters", "category": "id_category" })
, , , , .
=>
=> 15.6 , 17 .
, . . ., .
— , , — .
. , .
, , . .
, . _id .
$addToSet
.
db.test.aggregate([ // id { '$match': { type : "goods_attr", category: id_category } }, // , { '$project': { "title" : "$title.ru", 'value': "$attr.ru", 'category': "$category", '_id': 0 } }, { '$group' : { '_id': { 'category' :"$category", 'title': "$title"} , 'filters': { '$addToSet': "$value" } } }, { '$group' : { '_id' :"$_id.category", 'title':{ '$addToSet': { 'title': "$_id.title", 'filters': "$filters" } } } } ])
group :
...{ '$group' : { '_id': { 'category' :"$category", 'title': "$title"} , 'filters': { '$addToSet': "$value" } } }.... { "_id": { "category": "id", "title": " " }, "filters": [ "" ] } { "_id" : { "category" : "id", "title" : "" }, "filters" : [ " " ] } { "_id" : { "category" : "id", "title" : " " }, "filters" : [ "" ] }
group .
...{ '$group' : { '_id':"$_id.category", 'title':{'$addToSet': {'title': "$_id.title", 'filters': "$filters" }} } ...} { "_id" : "id_category", "title" : [ { "title" : " ", "filters" : [ " ", " ", " ", " " ] }, { "title" : " ", "filters" : [ "" ] }, { "title" : "", "filters" : [ " " ] }, { "title" : " ", "filters" : [ "" ] } ] }
, , . , , owner_id
_id .
db.test.aggregate([ { '$match' : { 'type' : "goods_attr", "category'':"id", '$or': [ {'title': '', 'attr': ' '}, {'title': ' ', 'attr_val': ' '} ] } }, { '$group': {'_id': "$owner_id", "attr": { '$push': "$title" }}}, { '$match': {"attr": {'$all': [ '', ' ' ] }}}, { '$project': {"_id":1 } } ])
_id .
Python
.
, , , ( — ) . , , .
ERP . , , - . , , .
python
, , .
exec
src = ''' result = 0 for i in xrange(100): result += i ''' assert '__' not in src, 'Prohibited to use symbols "__"' pr = compile(src, '<string>', mode='exec') glob = { '__builtins__':{ 'xrange':xrange } } exec(pr, glob) print glob['result']
eval
( )
src = 'max(5,7,3)' glob = { '__builtins__':{ 'max':max } } assert '__' not in src, 'Prohibited to use symbols "__"' print ( eval(src, glob) )
— :
assert '__' not in src, 'Prohibited to use symbols "__"'
- , :
__class__, __base__
python
glob = { '__builtins__':{ 'xrange':xrange } }
(import, type...) / .