猿问

如何动态构建查询过滤器

我正在使用 Go 来设置我自己的 API。由于我如何编写代码来动态创建/应用查询过滤器,我现在有点卡住了。它有效,但我想知道是否有更好的方法来完成下面的场景。


例如,我有一个带有复选框的搜索页面(1 个用于电子邮件,1 个用于名称)来缩小搜索范围。


// If I checked the email, the query would be like this

query findOne() {

  user(func: type(user)) @filter(eq(email, "john.doe@email.com")) {

    name

    email

    age

    home_address

  }

}


// If name checkedbox is also checked, it would be like this

query findOne() {

  user(func: type(user)) @filter(eq(email, "john") OR eq(name, "john")) {

    name

    email

    age

    home_address

  }

}

这是我到目前为止得到的,我认为有更好的方法来做到这一点:


func (s *Service) GetUser(email, name string) (*Users, error) {

    c := db.NewClient()

    defer db.Close()

    var u Users

    var filter string


    if email != "" && mobileNumber != "" {

      filter = fmt.Sprintf(`eq(email, "%s") OR eq(mobileNumber, "%s")`, email, mobileNumber)

    } else if email != "" && mobileNumber == "" {

      filter = fmt.Sprintf(`eq(email, "%s")`, email)

    } else if email == "" && mobileNumber != "" {

      filter = fmt.Sprintf(`eq(mobileNumber, "%s")`, mobileNumber)

    }


    q := fmt.Sprintf(`query findOne() {

        users(func: type("user")) @filter(%s) {

            name

            email

            home_address

            contact_number

        }

    }`, filter)

    ctx := context.Background()

    res, err := c.NewTxn().Query(ctx, q)

    if err != nil {

        return nil, err

    }

    if err = json.Unmarshal(res.Json, &u); err != nil {

        return nil, err

    }

    return &u, nil

}

有没有更好的方法来做到这一点而不是创造长期条件?


qq_花开花谢_0
浏览 130回答 2
2回答

慕婉清6462132

这是它的反射版本。基本上它枚举字段,获取值和字段名称以基于它们构建字符串数组。请不要说我经验不足,它可能还需要一些改进。import (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "reflect"&nbsp; &nbsp; "strings")type User struct {&nbsp; &nbsp; Id&nbsp; &nbsp; &nbsp; &nbsp;int&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; FullName string&nbsp;&nbsp; &nbsp; Phone&nbsp; &nbsp; string&nbsp;&nbsp; &nbsp; Mail&nbsp; &nbsp; &nbsp;string&nbsp;}func main() {&nbsp; &nbsp; u := &User{Id: 10, FullName: "John", Mail: "john@mail"}&nbsp; &nbsp; u2 := struct {&nbsp; &nbsp; &nbsp; &nbsp; id&nbsp; &nbsp;int&nbsp; &nbsp; &nbsp; &nbsp; name string&nbsp; &nbsp; }{10, "john"};&nbsp; &nbsp;// inline struct&nbsp; &nbsp; q := getQuery(&u2, "OR")&nbsp; &nbsp; fmt.Println(q)&nbsp; &nbsp;// typed struct&nbsp; &nbsp; q = getQuery(u, "AND")&nbsp; &nbsp; fmt.Println(q)}func getQuery(target interface{}, join string) string {&nbsp; &nbsp; var filters []string&nbsp; &nbsp; val := reflect.ValueOf(target).Elem()&nbsp; &nbsp; for i := 0; i < val.NumField(); i++ {&nbsp; &nbsp; &nbsp; &nbsp; value := val.Field(i)&nbsp; &nbsp; &nbsp; &nbsp; s :=fmt.Sprintf("%v",value);&nbsp; &nbsp; &nbsp; &nbsp; // this little trick is to check if it is an empty value&nbsp; &nbsp; &nbsp; &nbsp; // so don't generate empty condition expressions&nbsp; &nbsp; &nbsp; &nbsp; if s == "" {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;continue&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; fieldType := val.Type().Field(i)&nbsp; &nbsp; &nbsp; &nbsp; filters = append(filters, fmt.Sprintf(" eq(%s, %v) ", fieldType.Name, value))&nbsp; &nbsp; }&nbsp; &nbsp; return strings.Join(filters, join)}

慕的地6264312

我建议重构您的过滤器逻辑,如下所述:package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "strings")func getQuery(key, val string, filters *[]string) {&nbsp; &nbsp; if val != "" {&nbsp; &nbsp; &nbsp; &nbsp; *filters = append(*filters, fmt.Sprintf(`eq("%s", "%s")`, key, val))&nbsp; &nbsp; }}func main() {&nbsp; &nbsp; var filters []string&nbsp; &nbsp; email := "demo@demo.com"&nbsp; &nbsp; mobileNumber := "123456789"&nbsp; &nbsp; getQuery("email", email, &filters)&nbsp; &nbsp; getQuery("mobileNumber", mobileNumber, &filters)&nbsp; &nbsp; filter := strings.Join(filters, " OR ")&nbsp; &nbsp; fmt.Println(filter)}
随时随地看视频慕课网APP

相关分类

Go
我要回答