Mongodbチートシート:電子商取引、移行、一般的に使用される操作、およびトランザクションに関するビット



この投稿は、小さなmongodb



チートシートと、いくつかのレシピを使用したmongodb



長いクエリです。 小さなものが1か所に集められていると便利な場合がありますmongodb



興味がある人mongodb



誰でも自分に役立つものを見つけてください。







SQL vs. NOSQL



トピックに関するホリバーのキーで投稿が認識されることは望ましくありません。 SQL vs. NOSQL



そして、どこにでも賛否両論があることは明らかです。この場合、それはどこかに少し助けになり、どこかにあなたが対処しなければならなかったいくつかの例になります。 mongo shell



およびpython



例。







  1. mongodbの新しいバージョンへの移行

  2. 比較クエリと論理クエリ
  3. Mongodb、正規表現、インデックスなどでの全文検索
  4. 原子演算子(データの変更)
  5. Mongodbのトランザクションについて少し

  6. Mongodbの集約フレームワークとJOIN
  7. 例

  8. 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
      
      





データベース自体を更新しなくても、すべてが以前のように機能するわけではありません。 すぐに気づいたことから:







  1. ユニバーサル化と統一のために、メソッドupdate_one, insert_many, find_one_and_delete



    仕様に update_one, insert_many, find_one_and_delete



    ました
  2. また、統合のために、 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')
      
      





  1. copy_database



    メソッドを削除
  2. end_request()



    メソッドはend_request()



    さend_request()



    代わりにclose()



    を使用することをお勧めします。
  3. コミュニティの一部は、 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 } ] } )
      
      





テストコレクション内のこのクエリは、次のドキュメントを検索します。









$はフィールドの存在をチェックして存在します

$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

















 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()})
      
      





:









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
 ....{ $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" ] } } )
      
      





:









 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



, - — - . , , , , , , .







, - , . .







, , , -.







  1. ( )
  2. .


, , , — . , , .







().







:







  1. , .
  2. .


, , . :







 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 "__"'
















All Articles