GAE Go — How to use GetMulti with non-existent entity keys?
Asked Answered
B

3

12

I've found myself needing to do a GetMulti operation with an array of keys for which some entities exist, but some do not.

My current code, below, returns an error (datastore: no such entity).

err := datastore.GetMulti(c, keys, infos)

So how can I do this? I'd use a "get or insert" method, but there isn't one.

Bludge answered 6/3, 2013 at 16:17 Comment(0)
D
19

GetMulti can return a appengine.MultiError in this case. Loop through that and look for datastore.ErrNoSuchEntity. For example:

if err := datastore.GetMulti(c, keys, dst); err != nil {
    if me, ok := err.(appengine.MultiError); ok {
        for i, merr := range me {
            if merr == datastore.ErrNoSuchEntity {
                // keys[i] is missing
            }
        }
    } else {
        return err
    }
}
Deviationism answered 6/3, 2013 at 19:38 Comment(5)
you could shorten that block if you used a type assertion. if me, ok := err.(appengine.MultiError); ok { for { ... } }Octopod
Thanks. Is that what you meant?Deviationism
yep you can drop the else clause as well and just return err for one less line too :-)Octopod
In the else case there's a real error and we want to indicate some problem, so I think it makes sense to keep it.Deviationism
Ahhh yeah since you still need access to the err object. Good point.Octopod
P
2

I know this topic is up for more than a few days, but I like to post an alternative, using type switch.

if err := datastore.GetMulti(c, keys, dst); err != nil {
  switch errt := err.(type) {
  case appengine.MultiError:
    for ix, e := range errt {
      if e == datastore.ErrNoSuchEntity {
        // keys[ix] not found
      } else if e != nil {
        // keys[ix] have error "e"
      }
    }
  default:
    // datastore returned an error that is not a multi-error
  }
}
Policeman answered 12/7, 2018 at 18:54 Comment(0)
G
0

Thought I'd throw my answer in to display another usecase. The following will take in any number of keys and return all the valid keys only.

// Validate keys
var validKeys []*ds.Key
if err := c.DB.GetMulti(ctx, tempKeys, dst); err != nil {
    if me, ok := err.(ds.MultiError); ok {
        for i, merr := range me {
            if merr == ds.ErrNoSuchEntity {
                continue
            }
            validKeys = append(validKeys, tempKeys[i])
        }
    } else {
        return "", err
    }
} else {
    // All tempKeys are valid
    validKeys = append(validKeys, tempKeys...)
}
Gender answered 8/8, 2021 at 13:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.