0

I am attempting to update a document in firestore using the golang library. For some reason I am getting an error: "no field \"BirthYear\" error and I am not sure why. Birth year is definitely one of the values that I am attempting to update.

I assume that I have configured my struct incorrectly but I cannot see how. Here is my struct and my update code:

sharedstructs.Profile

type Profile struct {
    UID                string                `json:"UID" firestore:"UID"`
    ContactEmail       string                `json:"ContactEmail,omitempty" firestore:"ContactEmail"`
    BirthMonth         int64                 `json:"BirthMonth,omitempty" firestore:"BirthMonth"`
    BirthYear          int64                 `json:"BirthYear,omitempty" firestore:"BirthYear"`
    Gender             string                `json:"Gender,omitempty" firestore:"Gender"`
    Unit               string                `json:"Unit,omitempty" firestore:"Unit"`
    CurrentStatus      string                `json:"CurrentStatus,omitempty" firestore:"CurrentStatus"`
    Country            string                `json:"Country,omitempty" firestore:"Country"`
    ExperienceType     string                `json:"ExperienceType,omitempty" firestore:"ExperienceType"`
    DateJoined         time.Time             `json:"DateJoined,omitempty" firestore:"DateJoined"`
    Abilities          []Ability             `json:"Abilities,omitempty" firestore:"Abilities"`
    Goals              []Goal                `json:"Goals,omitempty" firestore:"Goals"`
    Roles              []Role                `json:"Roles,omitempty" firestore:"Roles"`
    TermsAndConditions []TermsAndConditions  `json:"TermsAndConditions,omitempty" firestore:"TermsAndConditions"`
    TimeZone           string                `json:"TimeZone,omitempty" firestore:"TimeZone"`
    BaselineTests      []BaselineTestResults `json:"BaselineTests,omitempty" firestore:"BaselineTests"`
    UpdatedDate        time.Time             `json:"UpdatedDate,omitempty" firestore:"UpdatedDate"`
    FirstName          *string               `json:"FirstName,omitempty" firestore:"FirstName"`
    LastName           string                `json:"LastName,omitempty" firestore:"LastName"`
    DisplayName        string                `json:"DisplayName,omitempty" firestore:"DisplayName"`
}

Update Function

func updateProfileWithSpecficValues(documentName string, values sharedstructs.Profile, overwriteValues []string) error {
    ctx := context.Background()
    app := firestorehelper.GetFirestoreApp()

    client, err := app.Firestore(ctx)
    if err != nil {
        return err
    }
    defer client.Close()

    //Set the updated date
    values.UpdatedDate = time.Now()
    wr, error := client.Doc(collectionName+"/"+documentName).Set(ctx, values, firestore.Merge(overwriteValues))
    if error != nil {
        return error
    }
    fmt.Println(wr.UpdateTime)
    //Assume success
    return nil
}
mornindew
  • 1,993
  • 6
  • 32
  • 54
  • Your code looks correct, you should `log.Printf("%v - %v", values, overwriteValues)` and check the result – thst Jan 02 '19 at 21:32

2 Answers2

0

https://godoc.org/cloud.google.com/go/firestore#Merge

Merge returns a SetOption that causes only the given field paths to be overwritten. Other fields on the existing document will be untouched. It is an error if a provided field path does not refer to a value in the data passed to Set.

You are sending no BirthYear (default value) in values, but BirthYear is specified in overwriteValues.

Dmitry Harnitski
  • 5,838
  • 1
  • 28
  • 43
  • Hmm, that would have made sense. I set a breakpoint and doublechecked both my values and my overwriteValues had "BirthYear" in it. Not sure why it is throwing that error – mornindew Jan 02 '19 at 22:34
  • Do you have not default value of `BirthYear` in every item in `values`? Missing that will cause an error. – Dmitry Harnitski Jan 02 '19 at 22:47
0

As of cloud.google.com/go/firestore v1.3.0, I don't think you can accomplish an update through Set(..., valueStruct, firestore.Merge(sliceOfPaths)) when valueStruct is the complete struct you might read or write to Firestore.

I receive an error string including the 'no field "[SomeFieldName]"' string the OP references, but there is more information in this error. If my sliceOfPaths refers to the names of two elements of my struct, say an int and a time.Time, I often receive an error such as 'no field "[NameOfMyIntField] for value 2020-09-14T00:00:00Z"' or vice-versa, with it trying to update my Firestore doc's time field with the integer.

I just used Update() rather than Set(). It's a little clunkier because you have to pass Update() a specially crafted subset of your original struct (a slice of firestore.Update), but it works.

mbaynton
  • 411
  • 4
  • 4
  • I have exactly the same problem: I'm trying to update firestore using Set with Merge options, but if I provide more than two paths, I always get an error "no field XXX for value YYY". How to use Update() ? I tried it but it does not seem trivial. I would have to use protoreflect in order to build a `firestore.Update` struct...but I don't want to experiment reflection right now... Maybe can you paste an example of how you used `Update()` - did you also use reflection? – user8285681 Oct 30 '20 at 12:01
  • I raised a separate question [here](https://stackoverflow.com/questions/64608798/updating-firestore-documents-in-golang-using-structs-or-protobuf-messages-as-d) – user8285681 Oct 30 '20 at 13:01