php mongodb - как выполнить запрос "INNER JOIN" - PullRequest
8 голосов
/ 30 сентября 2010

Я использую расширение 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

Ответы [ 5 ]

19 голосов
/ 01 октября 2010

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

Надеюсь, это было полезно.

14 голосов
/ 16 июля 2012

Забудьте о соединениях.

сделайте поиск в ваших новостях. Примените номер пропуска и ограничение для подкачки результатов.

$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] } } ); 

Затем, когда вы распечатываете новости, они могут отображать информацию о пользователях из коллекции пользователей на основе идентификатора пользователя.

Вы сделали 2 запроса к базе данных. Нет необходимости возиться с объединениями, выяснять имена полей и т. Д. ПРОСТО !!!

4 голосов
/ 14 января 2016

Если вы используете новую версию MongoDB (3.2), то вы получите нечто похожее с оператором $lookup.

Недостатки использования этого оператора заключаются в том, что он крайне неэффективен при работе с большими наборами результатов и поддерживает равенство только для совпадения, в котором равенство должно быть между одним ключом из каждой коллекции.Другое ограничение состоит в том, что правая коллекция должна быть неотмеченной коллекцией в той же базе данных, что и левая коллекция.

Следующая операция агрегации в коллекции news объединяет документы из news с документамииз коллекции users с использованием полей user_id из коллекции news и поля _id из коллекции users:

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);
?>
4 голосов
/ 30 сентября 2010

Возможно, вам лучше встроить «новости» в документы пользователей.

0 голосов
/ 04 сентября 2015

Вы не можете сделать это в mongoDB.А с версии 3 Eval () устарела, поэтому вам не следует использовать хранимые процедуры.

Единственный известный мне способ выполнить запрос на стороне сервера, включающий несколько коллекций, - это использовать Node.js или аналогичный.Но если вы собираетесь попробовать этот метод, я настоятельно рекомендую вам ограничить IP-адреса, разрешенные для доступа к вашему компьютеру, из соображений безопасности.

Кроме того, если ваши коллекции не слишком большие, вы можете избежать внутреннихприсоединяется к их денормализации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...