powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Работа с Mango (Perl+mongo)
5 сообщений из 5, страница 1 из 1
Работа с Mango (Perl+mongo)
    #38847036
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть у меня БД в 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
Работа с Mango (Perl+mongo)
    #38847134
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Какая-то ерунда выходит.
Второй вариант не подходит, документ пересоздается и если указать только отдельные поля, то только они и останутся в документе после обновления.
Но и первый вариант не подходит, выдает ошибку "Write error at index 0: The _id field cannot be changed from {_id: BinData} to {_id: BinData}".
...
Рейтинг: 0 / 0
Работа с Mango (Perl+mongo)
    #38847245
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Перешел на 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
Работа с Mango (Perl+mongo)
    #38847262
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сделал так:
Код: php
1.
$colChannels->update({'_id'=>$oid}, {'$set'=>{'channelName'=>$name, 'description'=>($desc||'')}});


В принципе, главный вопрос это решает.
Но хотелось бы еще сохранить порядок полей в документе.
Как это сделать с помощью Tie::IxHash я сам пока не пойму; у меня не hash, а hashref.
...
Рейтинг: 0 / 0
Работа с Mango (Perl+mongo)
    #38847269
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Просьба проверить, правильно ли я думаю?
Код: 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
5 сообщений из 5, страница 1 из 1
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Работа с Mango (Perl+mongo)
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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