Forum Discussion

Kev_B's avatar
Kev_B
Advisor
6 years ago

user_badges blank?

Hi,

I'm attempting to create a page to show off our Superusers, and I wanted to pull their yearly SU badges to show off how long they've been in the program.

I'm using the API browser in Studio to make sure I've got the right data before coding the next step, but the user_badges data for the users I'm searching is non-existent. The profile I'm viewing has earned 9 badges, so I'm baffled why this is blank.

API call:

SELECT user_badges FROM users WHERE id = '238'

Result:

{
  "status" : "success",
  "message" : "",
  "http_code" : 200,
  "data" : {
    "type" : "users",
    "list_item_type" : "user",
    "size" : 1,
    "items" : [ {
      "type" : "user",
      "user_badges" : {
        "type" : "user",
        "items" : [ ]
      }
    } ]
  },
  "metadata" : { }
}v

Appreciate any input on this, am I missing a constraint? Is this a bug? I've checked the documentation and the query seems to be correct. I've even done similar in the past and the query matches what I did there (that code isn't currently live for me to verify if this is just a problem with API Browser or Studio).

Thanks in advance 🙂

  • Hi Kev, I looked at this one for quite a while. This looks like an API browser issue, as the following API calls return the right data, even without credentials:

     

    • /api/2.0/search?q=SELECT+user_badges+FROM+users+WHERE+id+%3D%27238%27
    • /api/2.0/users/238

    You may also notice the API browser is showing the collection with type: "user" instead of type: "user_badge".

    Could you try putting the query in a simple component? Does the component get the right data when viewed by the user ("Lemmings")? How about other users?

    By design, we allow a user to learn about badges they haven't earned yet, but only when viewing their own badges. To make that work, the backend has different approaches for getting the data, depending on who is making the query & where. It's possible there could be an issue in just one of those approaches.

8 Replies

  • Kev_B,

    You are using the correct API to get user badges.

    Issue here is the user you are checking doesn't have any badges.

    Most of the time it happens when user is created directly through admin and not registered from the community registration process.

    Try using different user id  in your api request and see if it puts the same or different result in response.

  • Kev_B's avatar
    Kev_B
    Advisor
    6 years ago

    Thanks Parshant sadly I've used a few different users now and see the same result.

    The user was created through the registration process as it's one of my accounts and I remember going through the process.

    Any other ideas?

  • AndrewF's avatar
    AndrewF
    Khoros Oracle
    6 years ago

    Hi Kev, I looked at this one for quite a while. This looks like an API browser issue, as the following API calls return the right data, even without credentials:

     

    • /api/2.0/search?q=SELECT+user_badges+FROM+users+WHERE+id+%3D%27238%27
    • /api/2.0/users/238

    You may also notice the API browser is showing the collection with type: "user" instead of type: "user_badge".

    Could you try putting the query in a simple component? Does the component get the right data when viewed by the user ("Lemmings")? How about other users?

    By design, we allow a user to learn about badges they haven't earned yet, but only when viewing their own badges. To make that work, the backend has different approaches for getting the data, depending on who is making the query & where. It's possible there could be an issue in just one of those approaches.

  • Kev_B's avatar
    Kev_B
    Advisor
    6 years ago

    Thanks AndrewF 

    I'll test in a component over the next few days when I have a little more time, but checking your URL search query returned results for the user so the data is clearly there.

    Thanks for the help 😃

  • Kev_B's avatar
    Kev_B
    Advisor
    6 years ago

    AndrewF 

    I've got data when putting it in a component. The only bit I'm struggling with now is accessing the data items in user_badges.

    When I code:

     

    user.user_badges.size

     

    I'm given the correct count based on the data. What I want to do now is access the data for the badges.

    Using a <#list> didn't seem to work so I've tried delving into individual badge items 3 different ways:

     

    user.user_badges.data.items[0].title
    user.user_badges.items[0].title
    user.user_badges.items[0].badge.title

     

    For reference, I'm trying to pull the data into a list as follows:

    <#list user.user_badges.items as badge>
       ${badge.title}
    </#list>

    This is more trial and error than anything (and most likely my error). I've done similar before but have run a query specific to user_badges in user for specific ID. What I'm working with now is querying from a list (SELECT xxx FROM users WHERE login IN [list] etc) so it's new territory for me.

    Any suggestions appreciated.

  • Kev_B's avatar
    Kev_B
    Advisor
    6 years ago

    Not to worry - I missed a level in the data structure, my list now works:

    <#list user.user_badges.items as badge>
      ${badge.badge.title}
    </#list>
  • Claudius's avatar
    Claudius
    Boss
    4 years ago

    I am still struggling with navigating the user_badges return data and wondered if Kev_B could maybe share some of the code where he got it working.

    So I tried via the API browser to query SELECT user_badges FROM users WHERE id = '65' and got

    {
      "status" : "success",
      "message" : "",
      "http_code" : 200,
      "data" : {
        "type" : "users",
        "list_item_type" : "user",
        "size" : 1,
        "items" : [ {
          "type" : "user",
          "user_badges" : {
            "type" : "user",
            "items" : [ ]
          }
        } ]
      },
      "metadata" : { }
    }

    Which seems to follow the issue AndrewF described about API browser returning incomplete results.

    So I built my component like this

    <#assign allbadges = restBuilder().liql("SELECT user_badges FROM users WHERE id = '${(page.context.user.id)!'65'}'") />
    <#list allbadges.data.items as badge>
        ${badge}
    </#list>

    This returns a nice 😐 object output of with a map of an empty user and a user_badges map one level down

    InMemoryObjectInstanceTemplateModel{entity=InMemoryObjectInstance [fieldMap={type=user, user_badges=InMemoryObjectInstance [fieldMap={size=26, list_item_type=user_badge, items=[InMemoryObjectInstance [fieldMap={badge=InMemoryObjectInstance [fieldMap={icon_url=https://community.stage.dataiku.com/html/@6B716363DFAD3E73EB8A75D5A60C9A35/badge_icons/Public%20Alpha%20Tester.png, awarded=58, activation_date=Wed Oct 23 08:32:18 PDT 2019, description=Thank you for your feedback and participating in our Alpha Test!, id=14, type=badge, title=Alpha Test}.....

    As soon as I try to list through that user_badges collection by amending the code to

    <#list allbadges.data.items.user_badges as badge>


    all hell breaks loose and I only get a fat freemarker error that just shouts "Claudius, you don't understand what Freemarker sequences are":

    For "." left-hand operand: Expected a hash, but this has evaluated to a sequence (com.google.common.collect.Lists$TransformingRandomAccessList wrapped into f.t.DefaultListAdapter):
    ==> allbadges.data.items  [in template "preview" at line 10, column 12]

    I tried already to go list out user and user_badges separately by

    <#list allbadges.data.items[0] as user, user_badges>

    But that didn't get me much further either.

    Can someone help me on the right track to get a list of user badges from a LiQL call on the user collection?

  • Kev_B's avatar
    Kev_B
    Advisor
    4 years ago

    Hey Claudius 

    Sorry for taking a while - busy few weeks!

    I'll caveat my solution by saying I'm still learning, so it might not be 100% correct. I also haven't tested the solution I created in over 12 months so it might be that something changed in the API.

    I had to delve through 2 layers to get badge info to display. The original query seems the same as yours:

     

    SELECT user_badges FROM users WHERE id = user.id

     

    The data structure of what's returned seems to have 2 layers though, so I had to use a nested list to access the data for individual badges. So where I'd usually access the data by layer1.data.items, I then had to do layer2.user_badges.items

    I guess the visualisation would be something like this:

    1. Badge 1
      1. Name
      2. URL
      3. etc
    2. Badge 2
      1. Name
      2. URL
      3. etc

    Anyway, the code I used was:

     

    <#list badges.data.items as badgeItem>
    <#list badgeItem.user_badges.items as badge>
    # Do stuff with the badge data
    </#list>
    </#list>

     

    Like I say, I haven't actively tested this for a while, and I don't have any new badges within the confines of the existing component to test if it still works.