mongodb php - 如何执行“INNER JOIN”式查询

发布于 2024-09-25 12:23:26 字数 911 浏览 5 评论 0原文

我正在使用 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

I'm using the Mongo PHP extension.

My data looks like:

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"
}

How to run a query similar like this, from PHP?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

番薯 2024-10-02 12:23:26

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

我希望这对您有帮助。

MongoDB does not support joins. If you want to map users to the news, you can do the following

1) Do this at the application-layer. Get the list of users, and get the list of news and map them in your application. This method is very expensive if you need this often.

2) If you need to do the previous-step often, you should redesign your schema so that the news articles are stored as embedded documents along with the user documents.

    {
      "_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"
                }]
    }

Once you have your data in this format, the query that you are trying to run is implicit. One thing to note, though, is that analytics queries become difficult on such a schema. You will need to use MapReduce to get the most recently added news articles and such queries.

In the end the schema-design and how much denormalization your application can handle depends upon what kind of queries you expect your application to run.

You may find these links useful.
http://www.mongodb.org/display/DOCS/Schema+Design
http://www.blip.tv/file/3704083

I hope that was helpful.

娇俏 2024-10-02 12:23:26

忘记连接。

查找您的新闻。应用跳过编号和限制来对结果进行分页。

$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 次查询。无需搞乱连接和计算字段名称等。简单!

Forget about joins.

do a find on your news. Apply the skip number and limit for paging the results.

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

then loop through the collection and grab the user_id in this example you would be limited to 10 items. Now do a query on users for the found user_id items.

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

Then when you print out the news it can display user information from the user collection based on the user_id.

You did 2 queries to the database. No messing around with joins and figuring out field names etc. SIMPLE!!!

在梵高的星空下 2024-10-02 12:23:26

您最好将“新闻”嵌入到用户的文档中。

You might be better off embedding the "news" within the users' documents.

阳光下的泡沫是彩色的 2024-10-02 12:23:26

如果您使用新版本的 MongoDB (3.2),那么您将得到与 $lookup 运算符。

使用此运算符的缺点是,在大型结果集上运行时效率非常低,并且它仅支持匹配的相等性,其中相等性必须在每个集合中的单个键之间。另一个限制是右集合应该是与左集合位于同一数据库中的未分片集合。

以下针对 news 集合的聚合操作使用字段 user_idnews 中的文档与 users 集合中的文档连接起来news 集合中的 code> 和 users 集合中的 _id 字段:

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);
?>

If you are using the new version of MongoDB (3.2), then you would get something similar with the $lookup operator.

The drawbacks with using this operator are that it is highly inefficient when run over large result sets and it only supports equality for the match where the equality has to be between a single key from each collection. The other limitation is that the right-collection should be an unsharded collection in the same database as the left-collection.

The following aggregation operation on the news collection joins the documents from news with the documents from the users collection using the fields user_id from the news collection and the _id field from the users collection:

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

The equivalent PHP example implementation:

<?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);
?>
鸢与 2024-10-02 12:23:26

在 mongoDB 中你不能这样做。从版本 3 开始,Eval() 已被弃用,因此您也不应该使用存储过程。

我现在知道实现涉及多个集合的服务器端查询的唯一方法是使用 Node.js 或类似的方法。但如果您打算尝试此方法,出于安全原因,我强烈建议您限制允许访问您的计算机的 IP 地址。

另外,如果您的集合不太大,您可以避免内部联接对它们进行非规范化。

You can't do that in mongoDB. And from version 3 Eval() is deprecated, so you shouldn't use stored procedures either.

The only way I know to achieve a server side query involving multiple collections right now it's to use Node.js or similar. But if you are going to try this method, I strongly recommend you to limit the ip addresses allowed to access your machine, for security reasons.

Also, if your collections aren't too big, you can avoid inner joins denormalizing them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文