MongoDBは最近、新しい集計構造を導入しました。この構造は、マップが縮小された強力な構造に依存するのではなく、集計値を計算するためのより簡単なソリューションを提供します。
いくつかの単純なプリミティブを使用して、特定のMongoDBコレクションに含まれるドキュメントを計算、グループ化、形成、および設計することができます。この記事の残りの部分では、新しいMongoDB集約プラットフォームを最適に使用するためのマップ縮小アルゴリズムのリファクタリングについて説明します。完全なソースコードは、公開されているDatablendGitHubリポジトリにあります。
1。 MongoDB集約構造
MongoDBアグリゲーションプラットフォームは、1つのコマンドの出力がコンベヤーを介して送信されるか、次のコマンドの入力として使用されるようにリダイレクトされる、よく知られたLinuxパイプラインの概念に基づいています 。 MongoDBの場合、複数のオペレーターが1つのコンベヤーに統合され、ドキュメントフローの処理を担当します。
$ match、$ limit、$などの一部の演算子は、特定の基準セットが満たされた場合に、入力としてのドキュメントの受け入れをスキップし、同じドキュメントを出力します。 $projectや$unwindなどの他の演算子は、単一のドキュメントを入力データとして受け入れ、その形式を変更したり、特定の予測に基づいて複数のドキュメントを作成したりします。
$ group演算子は、最終的に複数のドキュメントを入力データとして受け入れ、対応する値を組み合わせてそれらを1つのドキュメントにグループ化します。これらの演算子の一部で式を使用して、新しい値を計算したり、文字列操作を実行したりできます。
複数の演算子が1つのパイプラインに結合され、ドキュメントのリストに適用されます。 コンベヤー自体はMongoDBコマンドとして実行され、コンベヤーの最後に出てきたすべてのドキュメントの配列を含む単一のMongoDBドキュメントになります。 次の段落では、オペレーターのコンベヤーとしての分子類似性のリファクタリングアルゴリズムについて詳しく説明します。実装ロジックを完全に理解するには、前の2つの記事を(再)読んでください。
2。分子類似性の配管
コンベヤーを特定のコレクションに適用すると、そのコレクションに含まれるすべてのドキュメントが最初のオペレーターへの入力として渡されます。 パイプラインを介して転送されるドキュメントの数を制限するために、このリストをできるだけ早くフィルタリングすることをお勧めします。私たちの場合、これは、ターゲットの谷本係数を決して満たさないドキュメント全体をフィルタリングすることを意味します。
したがって、最初のステップとして、指紋の数が特定のしきい値内にあるすべてのドキュメントを比較します。 40個の一意のフィンガープリントを含むターゲット接続でTanimotoファクター0.8をターゲットにすると、$match演算子は次のようになります。
{"$ match":
{"fingerprint_count":{"$ gte":32、 "$ lte":50}}。
}コード>
32から50までのフィンガープリントを持つ接続のみが次のパイプラインオペレーターに転送されます。 このフィルタリングを実行するために、$ match演算子は、phingerprint_countプロパティに定義したインデックスを使用できます。谷本係数を計算するには、特定の入力接続とターゲットとするターゲット接続の間の一般的なフィンガープリントの数を計算する必要があります。
指紋レベルで作業するには、$unwind演算子を使用します。 $ unwindは、配列要素を1つずつ削除し、指定された配列がその要素の1つに置き換えられたドキュメントストリームを返します。この例では、指紋に$unwindを適用します。したがって、各複合ドキュメントはn個の複合ドキュメントになります。nは複合ドキュメントに含まれる一意のフィンガープリントの数です。
{"$ unwind": "$ fingerprints"}
一般的なフィンガープリントの数を計算するには、まず、ターゲット接続のフィンガープリントリストにあるフィンガープリントを持たないすべてのドキュメントをフィルタリングします。 これを行うには、$ match演算子を再度使用します。今回は、指紋プロパティをフィルタリングします。この場合、ターゲット指紋リストにある指紋を含むドキュメントのみがサポートされます。
{"$ match":
{"fingerprints":
{"$ in":[1960、15111、5186、5371、756、1015、1018、338、325、776、3900、...、2473]}
}コード>
}コード>
ターゲット指紋リストにある指紋のみを照合するため、出力を使用して一般的な指紋の総数を計算できます。
これを行うために、$グループ演算子を複合接続に適用しますが、一致するフィンガープリントの数(オカレンスの数を合計することにより)、入力接続フィンガープリントの総数、およびスマイリーを含む新しいタイプのドキュメントを作成します。
{"$ group":
{"_id":"$compound_cid"。 、
"fingerprintmatches":{"$ sum":1}、
"totalcount":{"$ first": "$ fingerprint_count"}、
"smiles":{"$ first": "$ smiles"}
}コード>
}コード>
これで、谷本係数を計算するためのすべてのパラメーターができました。これを行うには、$プロジェクト演算子を使用します。この演算子は、idとsmilesの複合プロパティをコピーするだけでなく、Tanimotoという名前の新しく計算されたプロパティも追加します。
{コード>
"$ project"
:コード>
{コード>
"_ id"
:コード>
1
、コード>
"tanimoto"
:コード>
{コード>
"$divide"
:コード>
[コード>
"$fingerprintmatches。"
、コード>
{コード>
"$ extract"
:コード>
[コード>
{コード>
"$ add"
:コード>
[コード>
40
、コード>
"$ totalcount"
]コード>
}コード>
、コード>
"$fingerprintmatches。"
]コード>
}コード>
]コード>
}コード>
、コード>
"smiles"
:コード>
1
}コード>
}コード>
Tanimotoのターゲット係数が0.8の接続にのみ関心があるため、オプションの$ match演算子を使用して、この係数に達しない接続をすべて除外します。
{"$ match":
{"tanimoto":{"$ gte":0.8}
}コード>
完全なパイプラインのコマンドは以下にあります。
{"aggregate": "compounds"}、
"pipeline":[
{"$ match":
{"fingerprint_count":{"$ gte":32、 "$ lte":50}}
}、コード>
{"$ unwind": "$ fingerprints"}、
{"$ match":
{"fingerprints":
{"$ in":[1960、15111、5186、5371、756、1015、1018、338、325、776、3900、...、2473]}
}コード>
}、コード>
{"$ group":
{"_id": "$ Compound_cid"、
"fingerprintmatches":{"$ sum":1}、
"totalcount":{"$ first": "$ fingerprint_count"}、
"smiles":{"$ first": "$ smiles"}
}コード>
}、コード>
{"$ project":
{"_id":1、
"tanimoto":{"$divide":["$ fingerprintmatches"]、{"$ extract":[{"$ add":[89、 "$ totalcount"]}、"$fingerprintmatches"]}。 ]}、
"smiles":1
}コード>
}、コード>
{"$ match":
{"tanimoto":{"$ gte":0.05}}
}]
}コード>
このパイプラインの出力には、特定のターゲット接続に関連してTanimoto0.8以上の接続のリストが含まれています。このコンベヤーの視覚的表現は以下にあります:
3。結論
新しいMongoDB集約構造は、ユーザーがカード削減タイプのアルゴリズムをより簡単に表現できるようにする、使いやすい演算子のセットを提供します。 その下にあるコンベヤーの概念は、データを処理するための直感的な方法を提供します。
当然のことながら、このパイプラインパラダイムは、実装のGremlin FrameworkTinkerpopや実装のCypherNeo4jなど、さまざまなNoSQLアプローチで採用されています。
パフォーマンスの観点から、配管ソリューションは、削減マップの実装を大幅に改善します。
オペレーターは最初はMongoDBプラットフォームでサポートされているため、解釈されたJavascriptよりもパフォーマンスが大幅に向上します。 Aggregation Frameworkは分離された環境でも動作できるため、特に入力接続の数が多く、Tanimotoターゲットが少ない場合は、元の実装のパフォーマンスを簡単に上回ります。 MongoDBコマンドによる優れたパフォーマンス!