[英]mongodb php - how to do “INNER JOIN”-like query
我正在使用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
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
我希望這會有所幫助。
忘記加入。
查找您的新聞。 應用跳過編號和限制以分頁結果。
$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次查詢。 不用搞弄連接和弄清楚字段名稱等。簡單!!!
如果您使用的是新版本的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);
?>
您最好將“新聞”嵌入用戶的文檔中。
您不能在mongoDB中做到這一點。 從版本3開始,不推薦使用Eval(),因此也不應該使用存儲過程。
我知道現在要實現涉及多個集合的服務器端查詢的唯一方法是使用Node.js或類似方法。 但是,如果您要嘗試這種方法,出於安全原因,強烈建議您限制允許訪問您的計算機的IP地址。
另外,如果您的集合不太大,則可以避免內部聯接對它們進行規范化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.