Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Работа с Mango (Perl+mongo) / 5 сообщений из 5, страница 1 из 1
31.12.2014, 09:23
    #38847036
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с Mango (Perl+mongo)
Есть у меня БД в mongo.
В БД есть несколько коллекций документов. Мне нужно перебрать документы в этой коллекции и часть документов обновить.
Не пойму, как это должно происходить.
Для перебора коллекции использую такой код:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
my $colChannels = $mango->db()->collection('Channels');
my $curChannels = $colChannels->find();
my $index = 0;
while (my $rs = $curChannels->next)
{
	$index++;
	my $id = &bytes2hex($rs->{'_id'});
	my $name = $rs->{'channelName'};
	my $desc = $rs->{'description'};
	print "Channel $name, id $id\n";
}

sub bytes2hex($)
{
	my $data = shift;
	return unpack('H*', $data);
}

sub hex2bytes($)
{
	my $data = shift;
	return pack('H*', $data);
}



Данный код успешно выводит все документы из коллекции.
Атрибуты channelName и description это строки, атрибут _id это LUUID, в дампе он выглядит как
Код: plaintext
1.
2.
3.
4.
          "_id" => bless( {
                          "type" => "generic",
                          "data" => "{\271\330\21\252\307E\@\210\26\6\371\224m\a\212"
                        }, 'Mango::BSON::Binary' ),

Мне нужно обновить у этих документов некоторые атрибуты.
Для этого у коллекции есть метод update. Но как бы я не задавал первый аргумент (как $id, как &hex2bytes($id), как {'_id'=>$rs->{'_id'}}), код ничего не обновляет.

Вот у меня есть такой код (исходя из того, что для find и update используется один синтаксис запроса):
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
my $colChannels = $mango->db()->collection('Channels');
my $curChannels = $colChannels->find();
my $index = 0;
while (my $rs = $curChannels->next)
{
	my $id = &bytes2hex($rs->{'_id'});
	my $tmp = $colChannels->find({'_id'=>$rs->{'_id'}})->all;
	print Dumper($tmp);
	exit;
}


Но этот код возвращает пустые данные, т.е. запрос на поиск не возвращает данных.
Как его нужно указывать, чтобы он все-таки заработал?

И второй вопрос.
При выполнении update вторым аргументом идет структура (хеш).
В ней нужно указывать полное содержимое документа или только изменяемые данные?
То есть такой код:
Код: php
1.
$collection->update($oid, {foo => 'baz'});


он у документа $oid обновит только атрибут foo?
Или он у документа $oid оставит только атрибут foo и удалит все остальное?
Если последнее, то как нужно обновлять документы? Считывать весь документ, обновлять в нем данные и заносить в БД?
Другими словами, какой код мне использовать:
Код: php
1.
2.
$rs->{'channelName'} = "new name $index";
$colChannels->update($oid, $rs)


или
Код: php
1.
2.
$name = "new name $index";
$colChannels->update($oid, {'channelName'=>$name})



________________________
Мы смотрим с оптимизмом...
...в оптический прицел.
...
Рейтинг: 0 / 0
31.12.2014, 13:18
    #38847134
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с Mango (Perl+mongo)
Какая-то ерунда выходит.
Второй вариант не подходит, документ пересоздается и если указать только отдельные поля, то только они и останутся в документе после обновления.
Но и первый вариант не подходит, выдает ошибку "Write error at index 0: The _id field cannot be changed from {_id: BinData} to {_id: BinData}".
...
Рейтинг: 0 / 0
31.12.2014, 16:18
    #38847245
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с Mango (Perl+mongo)
Перешел на MongoDB, думал может там все будет работать.
Что-то ничего не пойму.

Есть такой код:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
my $colChannels = $db->get_collection('Channels');
my $curChannels = $colChannels->find();
while (my $rs = $curChannels->next)
{
	my $oid = &oid($rs->{'_id'});
	my $id = &bin2hex($rs->{'_id'});
...
	# обновление
	{
		my $data = {%$rs};
		delete $data->{'_id'};
		$data->{'channelName'} = $name;
		$data->{'description'} = $desc;
		#$colChannels->update({'_id'=>$oid}, $data);
		exit;
	}
...
}

sub oid($)
{
	my $data = shift;
	my $oid = MongoDB::BSON::Binary->new('data'=>$data, 'subtype' => MongoDB::BSON::Binary->SUBTYPE_UUID_DEPRECATED);
	return $oid;
}

sub bin2hex($)
{
	my $data = shift;
	return unpack('H*', $data);
}



С использованием SUBTYPE_UUID_DEPRECATED наконец начали находиться документы.
Но теперь какая-то ерунда с обновлением данных.
Во первых, я не могу обновить нужные поля в $rs и отправить данные обратно — в этом случае я получаю такое сообщение:
Код: plaintext
The _id field cannot be changed from {_id: BinData} to {_id: "{\x{00b9}\x{00d8}◄\x{00aa}\x{00c7}E@\x{0088}▬♠\x{00f9}\x{0094}m\x{008a}"}. at ... line 155.
Я попробовал скопировать хеш, удалить из него ключ и обновлять его. В принципе операция выполнилась, но:
1. Изменился порядок документа, он был первым в коллекции, теперь последний.
2. Порядок полей в документе перепутался.
3. Самое главное — изменились типы данных полей и их содержимое. UUID заменился на Binary, 1 заменился на NumberLong(1) и т.п.

Мне нужно просто пройтись по всей коллекции и изменить пару полей, не меняя более ничего.
Или Perl тут неподходящий инструмент?
...
Рейтинг: 0 / 0
31.12.2014, 17:05
    #38847262
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с Mango (Perl+mongo)
Сделал так:
Код: php
1.
$colChannels->update({'_id'=>$oid}, {'$set'=>{'channelName'=>$name, 'description'=>($desc||'')}});


В принципе, главный вопрос это решает.
Но хотелось бы еще сохранить порядок полей в документе.
Как это сделать с помощью Tie::IxHash я сам пока не пойму; у меня не hash, а hashref.
...
Рейтинг: 0 / 0
31.12.2014, 17:32
    #38847269
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Работа с Mango (Perl+mongo)
Просьба проверить, правильно ли я думаю?
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
my $colDomains = $db->get_collection('Domains');
my $curDomains = $colDomains->find();
while (my $rs = $curDomains->next)
{
	my $oid = &oid($rs->{'_id'});
	my $index = 0;
	my $batch = {};
	foreach my $item (@{$rs->{'availableChannels'}})
	{
		# $name = ..., $desc = ...
		$batch->{"availableChannels.$index.channelName"} = $name;
		$batch->{"availableChannels.$index.description"} = ($desc||'');
		$index++;
	}
	#$colDomains->update({'_id'=>$oid}, {'$set'=>$batch});
	print Dumper($batch);
}
...
Рейтинг: 0 / 0
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Работа с Mango (Perl+mongo) / 5 сообщений из 5, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]