8

Mongo PHP 拡張機能を使用しています。

私のデータは次のようになります。

users
{
  "_id": "4ca30369fd0e910ecc000006",
  "login": "user11",
  "pass": "example_pass",
  "date": "2010-09-29"
},
{
  "_id": "4ca30373fd0e910ecc000007",
  "login": "user22",
  "pass": "example_pass",
  "date": "2010-09-29"
}

news
{
  "_id": "4ca305c2fd0e910ecc000003",
  "name": "news 333",
  "content": "news content 3333",
  "user_id": "4ca30373fd0e910ecc000007",
  "date": "2010-09-29"
},
{
  "_id": "4ca305c2fd0e910ecc00000b",
  "name": "news 222",
  "content": "news content 2222",
  "user_id": "4ca30373fd0e910ecc000007",
  "date": "2010-09-29"
},
{
  "_id": "4ca305b5fd0e910ecc00000a",
  "name": "news 111",
  "content": "news content",
  "user_id": "4ca30369fd0e910ecc000006",
  "date": "2010-09-29"
}

PHP から、このようなクエリを実行するにはどうすればよいですか?

SELECT n.*, u.* 
FROM news AS n 
INNER JOIN users AS u ON n.user_id = u.id
4

5 に答える 5

19

MongoDB は結合をサポートしていません。ユーザーをニュースにマッピングする場合は、次のようにします。

1) アプリケーション層でこれを行います。ユーザーのリストを取得し、ニュースのリストを取得してアプリケーションにマップします。これが頻繁に必要な場合、この方法は非常に高価です。

2) 前のステップを頻繁に行う必要がある場合は、スキーマを再設計して、ニュース記事がユーザー ドキュメントと共に埋め込みドキュメントとして保存されるようにする必要があります。

    {
      "_id": "4ca30373fd0e910ecc000007",
      "login": "user22",
      "pass": "example_pass",
      "date": "2010-09-29"
      "news" : [{  
                   "name": "news 222",
                   "content": "news content 2222",
                   "date": "2010-09-29" 
                }, 
                {
                   "name": "news 222",
                   "content": "news content 2222",
                   "date": "2010-09-29"
                }]
    }

この形式でデータを取得すると、実行しようとしているクエリは暗黙的になります。ただし、このようなスキーマでは分析クエリが困難になることに注意してください。最近追加されたニュース記事やそのようなクエリを取得するには、MapReduce を使用する必要があります。

最終的に、スキーマ設計と、アプリケーションが処理できる非正規化の量は、アプリケーションが実行するクエリの種類によって異なります。

これらのリンクが役立つ場合があります。 http://www.mongodb.org/display/DOCS/Schema+Design http://www.blip.tv/file/3704083

お役に立てば幸いです。

于 2010-10-01T01:38:47.130 に答える
14

結合を忘れてください。

あなたのニュースで検索を行います。結果のページングにスキップ数と制限を適用します。

$newscollection->find().skip(20).limit(10);

次に、コレクションをループして user_id を取得します。この例では、10 項目に制限されます。次に、見つかった user_id 項目についてユーザーに対してクエリを実行します。

// replace 1,2,3,4 with array of userids you found in the news collection.
$usercollection.find( { _id : { $in : [1,2,3,4] } } ); 

次に、ニュースを印刷すると、user_id に基づいてユーザー コレクションからユーザー情報を表示できます。

データベースに対して 2 つのクエリを実行しました。ジョインをいじったり、フィールド名を考えたりする必要はありません。簡単です!!!

于 2012-07-16T19:40:52.717 に答える
5

新しいバージョンの MongoDB (3.2) を使用している場合は、$lookupオペレーターで同様の結果が得られます。

この演算子を使用することの欠点は、大規模な結果セットに対して実行すると非常に非効率的であり、各コレクションの単一のキー間で同等でなければならない一致に対してのみ同等をサポートすることです。もう 1 つの制限は、右側のコレクションは、左側のコレクションと同じデータベース内の分割されていないコレクションでなければならないということです。

コレクションに対する次の集計操作は、コレクションのフィールドとコレクションのフィールドを使用して、コレクションのドキュメントとnewsドキュメントを結合します。newsusersuser_idnews_idusers

db.news.aggregate([
    {
        "$lookup": {
            "from": "users",
            "localField": "user_id",
            "foreignField": "_id",
            "as": "user_docs"
        }
   }
])

同等の PHP 実装例:

<?php
$m = new MongoClient("localhost");
$c = $m->selectDB("test")->selectCollection("news");
$ops = array(
    array(
        "$lookup" => array(
            "from" => "users",
            "localField" => "user_id",
            "foreignField" => "_id",
            "as" => "user_docs"
        )
    )
);
$results = $c->aggregate($ops);
var_dump($results);
?>
于 2016-01-14T15:00:27.640 に答える
4

ユーザーのドキュメント内に「ニュース」を埋め込んだ方がよい場合があります。

于 2010-09-30T14:33:05.010 に答える