在我的MongoDB文档中,我有这样的对象
[_id] => MongoId Object (
[$id] => 52a46b44aabacb5c218b4567
)
[results] => Array (
[http://google.com] => Array (
[position] => 1
[data] => 42672
)
[http://bing.com] => Array (
[position] => 2
[data] => 9423
)
[http://yandex.com] => Array (
[position] => 3
[data] => 5513
)
)
我想将“bing.com”中的数据参数从9423更改为例如300.此外,我必须保持网站的顺序。它必须看起来像这样
[_id] => MongoId Object (
[$id] => 52a46b44aabacb5c218b4567
)
[results] => Array (
[http://google.com] => Array (
[position] => 1
[data] => 42672
)
[http://bing.com] => Array (
[position] => 2
[data] => 300
)
[http://yandex.com] => Array (
[position] => 3
[data] => 5513
)
)
这在Mongo中是否可以实现?
答案 0 :(得分:1)
为了清楚起见,我在下面使用mongo
shell包含了一些示例,但PHP等效项应该很容易解决。
我注意到您最初将您的网站列表建模为嵌入文档,但目前无法保证嵌入文档中字段的顺序保留,因此您应该使用数组。
此外,您不能在MongoDB中使用带有嵌入点(。)的字段名称,因此您不应计划将URL存储为字段名称(请参阅:Field name restrictions)。
为了在数组中查找元素,您需要按值(而不是字段名称)进行搜索,这样您的模式应该更像:
{
_id: ObjectId("52a46b44aabacb5c218b4567"),
results: [
{
site: 'http://google.com',
position: 1,
data: 42762
},
{
site: 'http://bing.com',
position: 2,
data: 9423
},
{
site: 'http://yandex.com',
position: 3,
data: 5513
}
]
}
假设数组site
元素是唯一的,您可以使用positional operator $
来查找和更新匹配的嵌入式文档。
例如,要执行“bing.com”data
值的更新:
db.sites.update(
// Match criteria
{
_id:ObjectId("52a46b44aabacb5c218b4567"),
'results.site':'http://bing.com'
},
// Update
{ $set: {
'results.$.data': 300 }
}
)
在MongoDB 2.4+中,您可以选择pushing to a sorted array,这也是在添加新条目时按排序顺序维护数组的有用方法。
值得注意的是,如果您计划在阵列中存储许多(即数千个)项目,则由于文档增长和更新大型阵列的复杂性,这会造成严重的性能损失。
答案 1 :(得分:1)
自MongoDB v2.5.2(2.6版本)起,字段issue的重新排序已得到修复。说过一种可以完全避免问题的方法是将结果作为数组而不是(子)文档。另请注意,您不应使用“。”作为关键名称的一部分。 使用2.4,使用以下内容,您将看到在_id = 1(子文档)的情况下有重新排序,但在_id = 2(数组)的情况下则没有。
$document = array("_id" => 1, "results" => array('http://google.com' => array('position' => 1, 'data' => 42672),
'http://bing.com' => array('position' => 2, 'data' => 9423),
'http://yandex.com' => array('position' => 3, 'data' => 5513)));
$coll->insert($document);
$document = array("_id" => 2, "results" => array(array('site' => 'http://google.com', 'data' => 42672),
array('site' => 'http://bing.com', 'data' => 9423),
array('site' => 'http://yandex.com', 'data' => 5513)));
$coll->insert($document);
$coll->update(array("_id" => 1), array('$set'=>array("results.http://bing.com.data"=>300)));
$coll->update(array("_id" => 2, 'results.site' => 'http://bing.com'), array('$set'=>array('results.$.data'=>300)));
答案 2 :(得分:0)
我很确定(与其他所有DBMS一样)您不能并且不应该依赖记录订单。
相反,我会建议您添加index
(在position
上,即db.people.ensureIndex( { position: 1 } )
)并查询按该字段排序的记录,i。 e。:db.collection.find().sort( { position: 1 } )