A space to discuss GraphQL queries, mutations, troubleshooting, throttling, and best practices.
Hi guys .. I cannot see a way to do this but is it possible to run a GraphQL mutation to delete ALL images for a product?
I need to regularly do a refresh for a product.
The way it stands, it seems I will have to do a request to get the existing product image ID's then perform a mutation to delete the image ID's that have been acquired.
Is there a better way?
Hey Mattayres,
great question, did you find an answer to it? 🙂
Cheers,
Matthias
I found this process super cumbersome too, they should add a delete all media mutation. Here is my laravel class that has all 3 graphQL queries (query for IDs/delete/re-add) for your reference:
https://gist.github.com/wasalwayshere/903def4d3b711f916ad5e49beaa67685
I am deleting all product images with the following method
I actually realized the productDeleteImages method is deprecated, and I should use productDeleteMedia instead.
This is what my new code looks like
public function deleteAllImages(User $shop, string $productId)
{
$mediaIds = $this->getMediaIds($shop, $productId);
if (empty($mediaIds)) {
return [];
}
// Split the mediaIds array into chunks of 200 items each
$mediaIdsChunks = array_chunk($mediaIds, 200);
foreach ($mediaIdsChunks as $mediaIdsChunk) {
$mutation = <<<GQL
mutation productDeleteMedia(\$productId: ID!, \$mediaIds: [ID!]!) {
productDeleteMedia(productId: \$productId, mediaIds: \$mediaIds) {
deletedProductImageIds
}
}
GQL;
$variables = [
'productId' => $productId,
'mediaIds' => $mediaIdsChunk,
];
try {
$result = $shop->api()->graph($mutation, $variables);
} catch (\Throwable $throwable) {
//Try again
Log::error('Error deleting images. Reason:' . $throwable->getMessage());
report($throwable);
$result = $shop->api()->graph($mutation, $variables);
}
if (!empty($result['errors'])) {
$errorMessage = 'Error deleting images. Reason:' . json_encode($result['errors']);
Log::error($errorMessage);
$exception = new \Exception($errorMessage);
report($exception);
throw $exception;
}
$this->graphqlRateLimitHandler->handleRateLimit($result);
}
return [];
}
public function getMediaIds(User $shop, string $productId)
{
$imageIds = [];
$cursor = 'null';
$hasNextPage = false;
do {
$query = <<<GQL
{
product(id: "{$productId}") {
media(first: 250, after: {$cursor}) {
pageInfo {
hasNextPage
}
edges {
cursor
node {
... on MediaImage {
id
}
}
}
}
}
}
GQL;
$result = $shop->api()->graph($query);
if (!empty($result['errors'])) {
$errorMessage = 'Error getting media ids. Reason:' . json_encode($result['errors']);
Log::error($errorMessage);
$exception = new \Exception($errorMessage);
report($exception);
throw $exception;
}
$this->graphqlRateLimitHandler->handleRateLimit($result);
if ($result['status'] === 429) {
continue;
}
$edges = $result['body']['data']['product']['media']['edges'];
$edges = $edges->toArray();
$imageIds = array_merge($imageIds, array_map(function ($edge) {
if (empty($edge['node']['id'])) {
return null;
}
return $edge['node']['id'];
}, $edges));
if (!empty($edges)) {
$lastEdge = end($edges);
if (isset($lastEdge['cursor'])) {
$cursor = '"' . $lastEdge['cursor'] . '"';
}
}
$hasNextPage = $result['body']['data']['product']['media']['pageInfo']['hasNextPage'];
} while ($hasNextPage);
if (empty($imageIds)) {
return [];
}
$imageIds = array_filter($imageIds);
$imageIds = array_values($imageIds);
return $imageIds;
}