Contentful logo

Contentful Community

Bug in `select` feature when attempting to return sys.id?

I’m querying “give me all entries with content type ZZZ-CONTENT-TYPE linked to Contentful entry with sys.id ZZZ-SYS-ID in the projects field, and only give me a few fields”

this works just fine:

const queryResponseThatWorks = await client.getEntries({
    'content_type': 'ZZZ-CONTENT-TYPE',
    'fields.projects.sys.id':'ZZZ-SYS-ID',
    'select': ['fields.name', 'fields.platform', 'fields.requestingPartner']
});

I get the response as expected with that subset of fields

but - and i’m doing this because i need to filter out duplicate entires (i’m running three queries and then merging the results, and hoping to use sys.id as a unique identifier rather than add my own) -

when i try:

const queryResponseThatDoesntWork = await client.getEntries({
    'content_type': 'ZZZ-CONTENT-TYPE',
    'fields.projects.sys.id':'ZZZ-SYS-ID',
    'select': ['sys.id', 'fields.name', 'fields.platform', 'fields.requestingPartner']
});

where ‘sys.id’ is not prepended with fields as shown in the documentation

it dumps the entire object, with all fields, as well as links objects that are in fields i didn’t ask for

this may be a very specific edge case, but let me know if you have any insight or if you need help reproducing it (happy to give you access to my space). i thought it might have something to do with resolving links, so i tried include: 0, but that didn’t have any effect except getting rid of some of the nested data in that linked field (which i still hadn’t requested). i even tried just requesting sys.id, but i still got the full object dump

thanks for any insight!
scotty

I am not able to reproduce this issue. I make a request to the Content Delivery API like this:

https://cdn.contentful.com/spaces/yadj1kx9rmg0/entries
  ?content_type=2PqfXUJwE8qSYKuM0U6w8M
  &select=fields.productName
  &access_token=fdb4e7a3102747a02ea69ebac5e282b9e44d28fb340f778a4f5e788625a61abe

and I get this as a response:

{
  "sys": {
    "type": "Array"
  },
  "total": 4,
  "skip": 0,
  "limit": 100,
  "items": [
    {
      "fields": {
        "productName": "SoSo Wall Clock"
      }
    },
    {
      "fields": {
        "productName": "Hudson Wall Cup"
      }
    },
    {
      "fields": {
        "productName": "Whisk Beater"
      }
    },
    {
      "fields": {
        "productName": "Playsam Streamliner Classic Car, Espresso"
      }
    }
  ]
}

and then I change to query to this (note the addition of sys.id to the select parameter):

https://cdn.contentful.com/spaces/yadj1kx9rmg0/entries
  ?content_type=2PqfXUJwE8qSYKuM0U6w8M
  &select=sys.id,fields.productName
  &access_token=fdb4e7a3102747a02ea69ebac5e282b9e44d28fb340f778a4f5e788625a61abe

and I get this response:

{
  "sys": {
    "type": "Array"
  },
  "total": 4,
  "skip": 0,
  "limit": 100,
  "items": [
    {
      "fields": {
        "productName": "SoSo Wall Clock"
      },
      "sys": {
        "id": "4BqrajvA8E6qwgkieoqmqO"
      }
    },
    {
      "fields": {
        "productName": "Hudson Wall Cup"
      },
      "sys": {
        "id": "3DVqIYj4dOwwcKu6sgqOgg"
      }
    },
    {
      "fields": {
        "productName": "Whisk Beater"
      },
      "sys": {
        "id": "6dbjWqNd9SqccegcqYq224"
      }
    },
    {
      "fields": {
        "productName": "Playsam Streamliner Classic Car, Espresso"
      },
      "sys": {
        "id": "5KsDBWseXY6QegucYAoacS"
      }
    }
  ]
}

This is all taken directly from the Content Delivery API documentation and making API calls using the in browser API request editor. Check it out here. I’ve not tried this directly using the CDA JS SDK, but it should work the same…

Thanks Charlie! Super appreciate the quick response, and you going through and trying to repro it

I actually adapted the example and sent the GET request by constructing the URL and, sure enough, it works as expected! (I get the sys.id field). So i was wrong in my suggestion/assumption that it’s a bug in the database layer with my use case (the only thing that was missing from your example was the filter on an id included in a nested/linked field, which i thought might be the edge case)

My working theory now is that it’s a bug in the JavaScript SDK - but i could also be misusing it - it’s not totally clear whether to pass select as an array or a comma-separated string, but the unexpected behavior could have something to do with passing it an array, and then the lib attempting to append ,sys to it (and maybe assumes query.select is a string)?

  /*
   * sdk relies heavily on sys metadata
   * so we cannot omit the sys property on sdk level
   * */
  function normalizeSelect (query) {
    if (query.select && !/sys/i.test(query.select)) {
      query.select += ',sys'
    }
  }

I found a workaround, which is to turn it into a string by calling join() e.g. ['field.someField', 'field.someOtherField'].join(',') on the array

This isn’t a bug in the JS SDK, but rather you’re supposed to supply a comma separated list of properties to show, not an array. The JS SDK is expecting a comma separated string and doesn’t test to see if the value supplied is a string or an array. The documentation on the use of the select operator with Javascript also shows using a comma separated list.

For example, here’s the (incorrect) query I did:

client.getEntries({
  content_type: 'page',
  select: ['sys.id','fields.title']
})

And here’s the request the Content Delivery API received:

?content_type=page&select%5B0%5D=sys.id&select%5B1%5D=fields.title

which when decoded turns into:

?content_type=page&select[0]=sys.id&select[1]=fields.title

And the CDA doesn’t understand what select[0] or select[1] means, so it ignores these unrecognized parameters which, in this case, means it returns all the entry fields including the sys object.

If you use the select operator with a comma separated list as a string (shown below), it works as expected.

client.getEntries({
  content_type: 'page',
  select: 'sys.id,fields.title'
})

Note that there is not a space in the string with the comma; using a space will cause an InvalidQuery error.

I hope this helps and clarifies exactly how to use the select operator.