What is the correct input for a bulk mutation operation?

I am trying to change a bulk of products’ categories, where my typical input was “id” and “category” , E.g; {
“input”: {
“id”: “gid://shopify/Product/7530183274553”,
“category”: “gid://shopify/TaxonomyCategory/aa-1-1”
}
}

But I can’t seem to get it to correctly read the input to enact this. I convert my data into a JSONL string with all sorts of variations: {“id”: … , “cat”: … }.. , [{“id”: … , “cat”: … }..] and { “input”: { “id”: … , “cat”: … } }

None of these seem to work. This is my mutation and query:

mutation_to_run_in_bulk = “”"
mutation ProductUpdate($input: ProductInput!) {
productUpdate(input: $input) {
product {
id
category {
id
}
}
userErrors {
field
message
}
}
}

query = “”"
mutation {
bulkOperationRunMutation(
mutation: “”" + json.dumps(mutation_to_run_in_bulk) + “”“,
variables: {},
resource: “Product”,
input: “”” + json.dumps(jsonl_lines) + “”"
) {
bulkOperation {
id
status
errorCode
createdAt
completedAt
objectCount
fileSize
url
}
userErrors {
field
message
}
}
}
“”"

Thanks.

1 Like

Hi @mttwthq1216

Is there any specific error message? What is the response data for calling Shopify API

Hey @mttwthq1216,

Just looking here, your productUpdate mutation looks correct. I do see an issue with the product category though, as a-1-1 isn’t valid. Perhaps you meant aa-1-1?

As for the bulk operation, make sure you are following the steps outlined here: Bulk import data with the GraphQL Admin API

For your jsonL file, there’s an online tool here you can use to validate it JSON Lines Validator

Let me know if that helps.

Hi Kyle,

I get the errors:
GraphQL Errors initiating bulk operation:

  • Field ‘bulkOperationRunMutation’ is missing required arguments: stagedUploadPath
  • Field ‘bulkOperationRunMutation’ doesn’t accept argument ‘variables’
  • Field ‘bulkOperationRunMutation’ doesn’t accept argument ‘resource’
  • Field ‘bulkOperationRunMutation’ doesn’t accept argument ‘input’

And I benchmark the time it takes so I know it’s not processing.

Thanks

Hi,

I forgot to disclosure that “a-1-1” was just an example, my taxonomy IDs are all correct.

Thanks, I will look into what you sent and try again, I just need a proven example of a bulk mutation operation working and what its input looks like.

  1. file: productUpdate.jsonl
{"product": {"id": "gid://shopify/Product/10255866560817","category": "gid://shopify/TaxonomyCategory/na"}}
{"product": {"id": "gid://shopify/Product/10255866560817","category": "gid://shopify/TaxonomyCategory/na"}}
{"product": {"id": "gid://shopify/Product/10255866560817","category": "gid://shopify/TaxonomyCategory/na"}}
{"product": {"id": "gid://shopify/Product/10255866560817","category": "gid://shopify/TaxonomyCategory/na"}}
  1. variables
  const variables = {
    input: [
      {
        filename: productUpdate.jsonl,
        mimeType: "text/jsonl",
        httpMethod: "POST",
        resource: "BULK_MUTATION_VARIABLES"
      }
    ]
  }
  1. graphql:
mutation stagedUploadsCreate($input: [StagedUploadInput!]!) {
  stagedUploadsCreate(input: $input) {
    stagedTargets {
      url
      resourceUrl
      parameters {
        name
        value
      }
    }
    userErrors {
      field
      message
    }
  }
}
  1. call shopify api
const stageResult = await shopify.graphql(
    stagedUploadsCreate, variables
  );
  1. Analyze response results
const {
    url,
    parameters,
  } = stageResult.stagedUploadsCreate.stagedTargets[0];

  logger.info('get upload url from shopify', url);
  1. Upload the JSONL file
const file = fs.readFileSync(productUpdate.jsonl);

  const form_data = new FormData();
  parameters.map(({name, value}) => form_data.append(name, value));
  form_data.append('file', file);

  let uploadUrl;
  try {
    const res = await axios.post(url, form_data, {
      headers: {
        "Content-Type": "multipart/form-data"
      }
    })


    parameters.filter(parameter => parameter.name === "key").forEach(parameter => {
      uploadUrl = parameter.value;
    });
    // uploadUrl = parameters.get("key");
  } catch (err) {
    logger.error(form_data);
    logger.error(err);
  }

  logger.info('upload file to shopify success', uploadUrl);
  1. Create a bulk mutation operation
const response = await shopify.graphql(bulkOperationRunMutation, {
      mutation: "productupdate",
      stagedUploadPath: uploadUrl
    });

Hi,

I think I’m getting close, trying this method of uploading jsonl file i get:

JSONL data saved to jsondata\data.jsonl
File uploaded successfully.

but then..

Error initiating bulk operation: [{‘message’: “Field ‘bulkOperationRunMutation’ is missing required arguments: mutation”, ‘locations’: [{‘line’: 3, ‘column’: 7}], ‘path’: [‘mutation’, ‘bulkOperationRunMutation’], ‘extensions’: {‘code’: ‘missingRequiredArguments’, ‘className’: ‘Field’, ‘name’: ‘bulkOperationRunMutation’, ‘arguments’: ‘mutation’}}, {‘message’: “Field ‘bulkOperationRunMutation’ doesn’t accept argument ‘resource’”, ‘locations’: [{‘line’: 5, ‘column’: 9}], ‘path’: [‘mutation’, ‘bulkOperationRunMutation’, ‘resource’], ‘extensions’: {‘code’: ‘argumentNotAccepted’, ‘name’: ‘bulkOperationRunMutation’, ‘typeName’: ‘Field’, ‘argumentName’: ‘resource’}}]

My input data is correct with JSONL verification, not sure where to go from here.

Is your ‘bulkOperaRunMutation’ structure like this?

const bulkOperationRunMutation = `
mutation bulkOperationRunMutation($mutation: String!, $stagedUploadPath: String!) {
  bulkOperationRunMutation(mutation: $mutation, stagedUploadPath: $stagedUploadPath) {
    bulkOperation {
      id
      completedAt
      createdAt
      errorCode
      fileSize
      objectCount
      partialDataUrl
      rootObjectCount
      status
      url
    }
    userErrors {
      field
      message
    }
  }
}
`;

No my structure was like this:

bulk_operation_mutation = '''
    mutation {
      bulkOperationRunMutation(
        stagedUploadPath: "%s",
        resource: "Product"
      ) {
        bulkOperation {
          id
          status
        }
        userErrors {
          field
          message
        }
      }
    }
    ''' % staged_upload_path

BulkOperaRunMutation only allows two parameters and does not include resource