Solved

Query all products with a given metafield value

swooders
Tourist
3 0 11

I am working a shopify app where I want to know the "status" of each product, which is either "complete" or "needing review". My app needs to pull all "needing review" products into the interface and show them in a paginated ResourceList. 

 

In order to pull all products with the status "needing review", I believe I two options:

1. Query from Shopify all products with the status "needing review"

2. Record in my own database the list of product ids that need review, and filter my queried products by those ids. 

 

I've been trying option (2.) however its extremely messy to simultaneously support pagination and search while also filtering queried products with a list of ids. For example, I will read 50 products for a page, but then only 35 will have the correct status, so then I end up with each of my pages having a different number of products. 

 

Option (1) would be  much easier if I am able to query Shopify products by what status I have given the product. However it seems like the only place in a product I can add custom information is in the metafields. From looking at this post https://community.shopify.com/c/Technical-Q-A/Querying-productvariants-by-metafields-in-GraphQL/m-p/... and the QueryRoot documentation (https://help.shopify.com/en/api/graphql-admin-api/reference/queryroot) it doesn't seem like its possible to query by metafield value. 

 

Basically, I'm really confused about how I can query products by a custom field.  

Accepted Solution (1)

Visely-Team
Shopify Partner
1843 210 488

This is an accepted solution.

Unfortunately, there is no way to query products by metafield value or any other "custom" field value.

Sergiu Svinarciuc | CTO @ visely.io
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution!
- To learn more about the awesome stuff we do head over to visely.io or our blog

View solution in original post

Replies 36 (36)

Visely-Team
Shopify Partner
1843 210 488

This is an accepted solution.

Unfortunately, there is no way to query products by metafield value or any other "custom" field value.

Sergiu Svinarciuc | CTO @ visely.io
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution!
- To learn more about the awesome stuff we do head over to visely.io or our blog
simonhaenisch
Shopify Partner
16 1 35

Need this as well... one of the main reasons we want to use private meta-fields for our app would be so that we can retrieve a list of products that we have tagged. Having to sync that with another DB just because the meta fields aren't queryable is somewhat cumbersome.

 

Is adding a query option for (private) meta-fields something that would be considered to be added to the API? It would already be sufficient if it's as simple as being able to query for a key name.

 

Example of what it could look like to query all products that have a private meta-field with key "status":

 

query getProductsWithMetaField {
  products(first: 5, query: "private_meta_field:status") {
    edges {
      cursor
    }
  }
}
swooders
Tourist
3 0 11

Thank you so much for your response! What is the recommended/standard way to add information about each product in a queryable way? I imagine it's fairly common for apps to need to query products by some information that they added to each product. Is the only solution to copy everything into a separate database to made the data queryable? 

 

If the solution is a separate database, how do we manage syncing the database to ensure its up to date with all the merchant's products? Will web hooks capture all updates to the products?

 

Thank you!

 

Visely-Team
Shopify Partner
1843 210 488

Unfortunately, yes. As to the ways to ensure all updates are caught, you'd use webhooks + scheduled Products REST API with updated_at_min filter to do reconciliation on possible missed updates.

Sergiu Svinarciuc | CTO @ visely.io
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution!
- To learn more about the awesome stuff we do head over to visely.io or our blog
raymmondxma
Tourist
5 0 2

use tags

simonhaenisch
Shopify Partner
16 1 35

use tags

Unfortunately tags are public-facing, e. g. the shop customer will be able to filter the catalog by tags. Not really a good place to store app-specific data.

devlife
Shopify Partner
9 0 5

This is no longer true the following code works:

 

query Diamonds {

  collection(handle: "best-selling-diamonds") {

    handle

    products(first: 5, filters:

       { productMetafield: {

          namespace:"diamond", key:"shape", value:"OVAL" } })

           {

            edges {

             node {

              handle

              title

              metafield: metafield(namespace: "diamond", key:"shape"){

              value

              description

              type

             }

           }

          }

         }

        }

       }

 

You need to make sure you're namespaces are all lowercase, the metafield is exposed to the storefront API, and it is enabled is the Shopify filtering app. If you need any more help @ me.

Bytebender
Shopify Partner
1 0 0

I try to sync data from our system to the Shopify store. My preferred solution would be to store our key in the Product meta field. Witch works fine so far. But because there is no way to look up the product by the meta field value there is no easy way to find the product again. After researching the admin graph QL and rest API I feel this feature is still missing. I see this thread got a lot of attention. My Questions would be:

  • Is there a UserVoice feedback page to request features?
  • To add that capability it seems such a minor thing to do to me. is it likely that this will ever happen?
BohdanNikitchuk
Shopify Partner
5 0 1

@Visely-Team more than 3 years have passed, are there any updates with it? I think it is an urgent feature that can help a lot with developing.

EdLazor
Excursionist
21 0 7

Agreed - the Admin Inventory section definitely needs to support more advanced filters, including filters by collection and filters by all product properties and metafields. Not having this drastically complicates the process of inventory management, resulting in having to spend much more time doing this.

HunterWebs
Visitor
1 0 0

This is incredibly sad to hear. I have been thinking about another possible work around. In case those reading are interested.

The idea is to download an entire list (of products for example) from Shopify. Then write some custom code to loop through each one to find a match. So basically download the entire Shopify list to your server for the purpose of finding just one record.

It is incredibly inefficient. Not recommended if you're trying to built a customer facing search feature. But in my case I wish to sync a local data source with Shopify via something other than the Shopify ID. The script itself will be run automatically over night, or manually by a developer. So the lack of efficiency won't really matter in this case.

policenauts
Shopify Partner
207 10 67

Any update to this given the recent Unite announcements related to metafields? 

dechimp
Shopify Partner
6 0 7

This would be a great feature to have. The current workaround seems pretty cumbersome, having to download your entire product database on an automatic and frequent basis, as per https://www.shopify.com/partners/blog/shopify-metafields

 

A very costly operation on both ends, IMO.

 

SebastianH
Shopify Partner
2 0 11

Using the new metafields options would be so much more of value if one can query orders, product etc. by meta fields

Dr. Sebastian Herden | Founder @ Y-Core Invest
PhD in computer science “model driven configuration management” | digital marketer, eCommerce owner, author and speaker
greg-gkr
Shopify Partner
21 0 8

Agreed, not having this just makes for cumbersome error prone solutions.

DazC
Excursionist
17 0 15

How is this still not a thing?  The only way you can return an array of products in Liquid is using an internal dummy collection?

dechimp
Shopify Partner
6 0 7

I'm pretty sure this topic was created before the metafield system had been revamped.  I don't have an updated answer, but it might be worth checking again.  Most likely, only the GraphQL version of the API would support this, if anything does.

DMiradakis
Tourist
7 0 9

I also have a use case for this. Shopify needs to add this!

Attrexx
Excursionist
17 1 6

Just throwing an idea in the mix:

can a specific Tag be assigned to a product if that product has a certain metafield value?
And then use that tag for queries.
Adding tags to hundreds of products according to already assigned metafield values could be a task too big for some.

Professional Web Products & Services • Website Development & Online Advertising on an European scale
PatchPat
Tourist
3 0 0

I've been researching this and so far the answer seems to be "not without API access" aka you have to find/subscribe to/custom-develop an app that can create that flow. Such as alloy automation or arigato or Shopify Flow (only available for the more expensive Shopify plans). 

 

I'm currently trying to learn how to develop my own custom app to do that, because I have seriously EVERYTHING else I need automated.

devlife
Shopify Partner
9 0 5

Is this what you are all looking for? You will need the filtering enabled in the Shopify Search & Filter app.


query tumbleDryProducts {
  collection(handle: "filterable-collection") {
    handle
    products(first: 1,
     filters: {
        productMetafield:{
          namespace:"product_care",
          key:"drying_instructions",
          value:"tumble dry"
        }
      }) {
      edges {
        node {
          id
          title
        }
      }
    }
  }
}
 
There is a reference to doing this on the Shopify docs: https://shopify.dev/api/examples/filter-products#query-products-by-metafield-value
 
However, I'm having some issues getting it working and have opened a discussion on Github:
dechimp
Shopify Partner
6 0 7

I remember trying something like that and getting bizarre results as well.  I just assumed that the current shopify API doesnt support this GraphQL syntax for metafields.

 

[edit] Thanks for putting in that bug report!

devlife
Shopify Partner
9 0 5

It was kind of an issue from my side in the end. My metafeilds had namespaces that started with a capital that broke it 🙃.

dechimp
Shopify Partner
6 0 7

Metafield namespaces/keys with spaces can also break things.  It's probably best to use lowercase letters, numbers, underscores and hyphens and nothing else.

DiegoPelaez
Shopify Partner
17 1 11

Just to add in to this thread based on the latest responses.
Based on @devlife suggestion we can now filter by metafields but through a collection. https://shopify.dev/custom-storefronts/products-collections/filter-products#query-products-by-metafi...


Requirements:

  • The metafield must have been added as a filter in the "Search & Discovery app" or the Filters in the Navigation settings. 
  • The metafield must be of one of these types: single_line_text_fieldbooleannumeric_integernumeric_decimal
  • The Storefront API used must be 2022-04 or higher. I tested it with 2022-10
  • The metafield must be exposed to the Storefront API
    Screen Shot 2022-10-21 at 3.05.14 pm.png
  • Also the collection must be available to the channel of your storefront API.

Knowing that as of today, we have a limit of 5000 products for filters to work in a normal store (see https://help.shopify.com/en/manual/online-store/search-and-discovery/filters)
Screen Shot 2022-10-21 at 3.07.28 pm.pngI decided to test if that restriction applies to the Storefront API, I tested it with a collection with 11769 products and I was able to get filtered results as expected. So it seems that at this stage we don't have this limitation in the Storefront API

devlife
Shopify Partner
9 0 5

Thanks for that post it should be the accepted answer, and to add onto this even further, you can query multiple metafields like so:

 

  query Diamonds {
    collection(handle: "diamonds") {
      handle
      products(first: 30, filters: [{productMetafield: {namespace: "diamond", key: "shape", value: "Round"}},{productMetafield: {namespace: "diamond", key: "shape", value: "Oval"}}] ) {
        edges {
          node {
            handle
            title
          }
        }
      }
    }
  }

 Hopefully, this helps someone.

adamgen
Shopify Partner
10 0 5

Testing it on the Shopify graphiql, I'm sending this query:

 

query tumbleDryProducts {
    collection(id: "gid://shopify/Collection/70598819862") {
        handle
        products(first: 1, filters: [{productMetafield: {namespace: "diamond", key: "shape", value: "Round"}}] ) {
            edges {
                node {
                    id
                    title
                }
            }
        }
    }
}

 

But I get this result:

 

{
  "errors": [
    {
      "message": "Field 'products' doesn't accept argument 'filters'",
      "locations": [
        {
          "line": 4,
          "column": 24
        }
      ],
      "path": [
        "query tumbleDryProducts",
        "collection",
        "products",
        "filters"
      ],
      "extensions": {
        "code": "argumentNotAccepted",
        "name": "products",
        "typeName": "Field",
        "argumentName": "filters"
      }
    }
  ]
}

 

It also prevented me from sending the handle as a filter for collections saying that it doesn't exist and I must use an id. And it also happens on old APIs. Any idea what's wrong?

Fractional VP R&D for E-commerce
adamgen
Shopify Partner
10 0 5

I was using the admin api instead of the storefront API, in case someone finds it useful.

 

Fractional VP R&D for E-commerce
tokito1
Shopify Partner
1 0 0

Can you check if it is correct. I try query with Storefront API and it only query 1000 of 27638 product in my collections. If product belong to the first 1000 it will show if not it will return 0 product

policenauts
Shopify Partner
207 10 67

@DiegoPelaez thank you for the detailed guide. I'm trying to follow the instructions and am getting stuck at the step of exposing metafields to the Storefront API. I have a public app in development and have generated a Storefront access token with all unauthenticated scopes, and the app itself has scope read_products. I have installed my app on a development store.

 

When I try to use metafieldStorefrontVisibilityCreate to expose my metafield to the Storefront API, I get this error: 

 

Access denied for metafieldStorefrontVisibilityCreate field. Required access: API client to have access to the owner type and namespace.

 

When I look at the metafield itself in the Shopify Admin, I also don't see that option to check the box for "Expose this metafield to the storefront API requests" like in your screenshot. What am I doing wrong? 

 

Thank you!

devlife
Shopify Partner
9 0 5

@policenauts They have just changed it in the last few days the option now sits here:

devlife_0-1670509882476.png

 

policenauts
Shopify Partner
207 10 67

@devlife thanks for the quick response. That box was already checked on my metafield by default so I'm not sure what I'm doing wrong. 

 

When I run the sample query here (TumbleDryProducts) but add in my own collection handle/id, the Storefront API query works, but it doesn't actually apply the metafield filter - it simply returns all the products in the collection. 

 

One thing is I am hoping to run this query on the server using node.js (not as part of an actual merchant storefront) and am currently testing using Postman - this should still work, right? 

 

My Storefront API query:

 

Endpoint: https://{mydevstore}.myshopify.com/api/2022-10/graphql.json

 

query tumbleDryProducts {
  collection(id: "gid://shopify/Collection/227683827876") {
    handle
    products(first: 1,
     filters: { // this filter isn't doing anything, I can change the properties to any random string
        productMetafield:{
          namespace:"custom.product_metafield2",
          key:"product_metafield2",
          value:"55555"
        }
      }) {
      edges {
        node {
          id
          title
        }
      }
    }
  }
}

 

My metafield:

 

Screen Shot 2022-12-08 at 7.18.43 AM.png

 

Search & Discovery filter app: 

 

Screen Shot 2022-12-08 at 7.20.44 AM.png

 

What else am I missing here in order for the query to actually filter based on the metafield value? Thank you. 

policenauts
Shopify Partner
207 10 67

OK, silly mistake - I realized I had my namespace incorrect in the filter. When I input the correct namespace, the correct filtered product appears. And now the query isn't returning products that don't meet the criteria - not sure if there was some kind of timing thing going on or what, but somehow now it's working. Thank you for your help. 

policenauts
Shopify Partner
207 10 67

Adding one more requirement per this thread - the product must also be published to online channel.

 

Based on my understanding and testing, here are the requirements again for completeness:

  1. The metafield must have been added as a filter in the "Search & Discovery app" or the Filters in the Navigation settings. 
  2. The metafield must be of one of these types: single_line_text_fieldbooleannumeric_integernumeric_decimal
  3. The Storefront API used must be 2022-04 or higher.
  4. The product must be available to both online channel as well as the channel of your Storefront API
  5. The collection must be available to the channel of your storefront API
  6. The metafield must "allow read requests from the Storefront API" (currently available as a checkbox in the metafield definition)
policenauts
Shopify Partner
207 10 67

I'm testing this with a merchant who has 95k products in their Collection, and unfortunately this isn't working the way we need it to. The first couple of times, the Shopify API returned an "Internal error. Looks like something went wrong on our end." After that it wouldn't error, but it only returned empty results. 

 

When searching for a product that is listed early on in the collection (<100), it works. However, when we started querying for products later on in the Collection, the query returns empty data. I was optimistic when I read that @DiegoPelaez had luck querying a collection with over 10k products, but perhaps 95k is simply too much. 

 

Anyone have any ideas or workarounds? One ugly idea would be to loop through the too-big collection on an ongoing basis and programmatically create smaller collections that we can filter against - however, that's going to be a lot to manage (and a lot of API calls for that merchant). 

devlife
Shopify Partner
9 0 5

More of a limitation than a requirement but I lost tons of time due to not knowing this. The metafield values you search for have to be exact you can't say Greater than X value or less than X value.

 

For example, if you have a `product.weight_in_grams` metafield you can't do a query to say show me all products that have a weight_in_grams greater than 150. 

 

I'm 99% sure of this but would love to be proven wrong. I ended up using Algolia.