2010-09-30 95 views
8

Estoy usando la extensión de PHP de Mongo.mongodb php - cómo hacer la consulta tipo "INNER JOIN"

Mis datos se parece a:

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

cómo ejecutar una consulta similar como este, desde PHP?

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

Respuesta

4

Puede ser mejor incluir las "noticias" en los documentos de los usuarios.

+0

mejor respuesta, nosql trata sobre la opción de dejar g cosas van para que las nuevas estructuras cobren vida –

18

MongoDB no admite uniones. Si desea asignar usuarios a las noticias, puede hacer lo siguiente

1) Haga esto en la capa de aplicación. Obtenga la lista de usuarios, obtenga la lista de noticias y asócielos en su aplicación. Este método es muy costoso si lo necesita a menudo.

2) Si necesita hacer el paso anterior a menudo, debe rediseñar su esquema para que los artículos de noticias se almacenen como documentos incrustados junto con los documentos del usuario.

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

Una vez que tenga sus datos en este formato, la consulta que está tratando de ejecutar está implícita. Una cosa a tener en cuenta, sin embargo, es que las consultas de análisis se vuelven difíciles en dicho esquema. Tendrá que usar MapReduce para obtener los artículos de noticias agregados más recientemente y tales consultas.

Al final, el diseño del esquema y la cantidad de desnormalización que su aplicación puede manejar depende del tipo de consultas que espere que se ejecute su aplicación.

Puede encontrar estos enlaces útiles. http://www.mongodb.org/display/DOCS/Schema+Design http://www.blip.tv/file/3704083

espero que haya sido útil.

+0

Si está almacenando artículos de noticias enteros integrados con sus usuarios, ¿es el límite de almacenamiento de objetos de 4M una preocupación? – jocull

+0

Puede usar dbrefs en lugar del documento real http://docs.mongodb.org/manual/applications/database-references/ – Optimus

14

Olvídate de las combinaciones.

encuentre sus novedades. Aplique el número de omisión y el límite para paginar los resultados.

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

a continuación, recorrer la colección y agarrar el user_id en este ejemplo que se limitaría a 10 elementos. Ahora haga una consulta sobre los usuarios para los elementos user_id encontrados.

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

Luego, cuando se imprima la noticia que puede mostrar información de usuario de la colección de usuario basada en la user_id.

Ha hecho 2 consultas a la base de datos. No perder el tiempo con combinaciones y averiguar los nombres de los campos, etc. ¡SIMPLE!

0

No se puede hacer eso en mongoDB. Y a partir de la versión 3, Eval() está en desuso, por lo que tampoco debe usar procedimientos almacenados.

La única forma que conozco de lograr una consulta del lado del servidor que implique varias colecciones en este momento es usar Node.js o similar. Pero si va a probar este método, le recomiendo que limite las direcciones IP permitidas para acceder a su máquina, por razones de seguridad.

Además, si sus colecciones no son demasiado grandes, puede evitar uniones internas que las desnormalicen.

4

Si está utilizando la nueva versión de MongoDB (3.2), entonces usted podría conseguir algo similar con el operador $lookup que se puede comparar con una combinación externa izquierda en SQL.

Los inconvenientes con el uso de este operador son que es muy ineficiente cuando se ejecuta a través de grandes conjuntos de resultados y sólo es compatible con la igualdad para el partido en el que la igualdad tiene que ser entre una sola clave de cada colección. La otra limitación es que la colección correcta debe ser una colección no filmada en la misma base de datos que la colección izquierda.

la siguiente operación de agregación en la colección news se une a los documentos de news con los documentos de la colección users utilizando los campos user_id de la colección news y el campo _id de la users colección:

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

El equivalente Implementación de ejemplo 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); 
?>