Golang MongoDB не возвращается по условному запросу - PullRequest
0 голосов
/ 31 января 2019

У меня есть эта функция, которая использует официальный драйвер mongo-go (https://github.com/mongodb/mongo-go-driver)

func FindItemMongo(dataStruct interface{}, subItemKey string, collectionName string)(){
    fmt.Println("inside FindDataMongo in Controller")
    localDB := DB
    coll := localDB.Collection(collectionName)
    ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
    var searchData []uint8
    if subItemKey==""{
        fmt.Println("inside no key searchData")
        searchData, _ = bson.Marshal(bson.M{"data": dataStruct})
        fmt.Println("value of searchData")
        fmt.Println(searchData)
        fmt.Println("value of reflect type of searchData")
        fmt.Println(reflect.TypeOf(searchData))
    }else{
        reflectItem := reflect.ValueOf(dataStruct)
        subItem := reflectItem.FieldByName(subItemKey)
        subItemString := subItem.Interface().(string)
        searchData, _ =  bson.Marshal(bson.M{"data": bson.M{strings.ToLower(subItemKey): bson.M{"$eq": subItemString}}})
        fmt.Println("value of searchData")
        fmt.Println(searchData)
        fmt.Println("value of reflect type of searchData")
        fmt.Println(reflect.TypeOf(searchData))
    }
    cursor, err := coll.Find(ctx, searchData)
    if err != nil {
        log.Fatal(err)
    }
    defer cursor.Close(ctx)
    var returnBson []map[string]interface{}
    var result bson.M
    for cursor.Next(ctx) {
        err := cursor.Decode(&result)
        if err != nil { log.Fatal(err) }
        fmt.Println("value of found parsed")
        fmt.Println(result)
        returnBson = append(returnBson, result)
    }
}

), который пытается найти данные в базе данных для двух условий, связанных с оператором if.Если subItemKey не определен, то он ищет точное совпадение с переданной структурой, если ключ определен, то он ищет совпадение в данных, используя оператор $eq только для определенного поля.

Это работает для условия, когда subItemKey пуст. Например:

database.FindItemMongo(dataStruct, "", "users")

Дает

api       | 1:36:55 app         | value of found parsed
api       | map[_id:ObjectID("8494398fsfd") data:map[email:qwer password:wer token:...]]

Однако, если я использую команду:

database.FindItemMongo(dataStruct, "Email", "users")

Я ничего не получаю.

Что-то не так с тем, как я определяю searchData в операторе else, и я не уверен, что. Кто-нибудь видит, что идет не так?

РЕДАКТИРОВАТЬ

Я должен отметить, что результат

    unmarshalledSearch := bson.M{"data": bson.M{strings.ToLower(subItemKey): bson.M{"$eq": subItemString}}}
    fmt.Println("value of unmarshalledSearch")
    fmt.Println(unmarshalledSearch)

равен

api       | value of unmarshalledSearch
api       | map[data:map[email:map[$eq:qwer]]]

, который совпадает с форматом данных, возвращаемых иззапрос пустого поля. Это суть проблемы - если тПохоже, что searchData правильно отформатирован, почему курсор не возвращается ни с какими результатами?

Ответы [ 3 ]

0 голосов
/ 03 февраля 2019

Учитывая структуру Login

type Login struct {
    Email    string `json:"email"`
    Password string `json:"password"`
    Token    string `json:"token"`
}

Предполагая, что у вас есть данные как

{data: {email: "name@example.com", password: "password", token: "token"}}

Когда subItemKey пусто, вы ищете точнокак выше.Но при поиске с использованием только электронной почты синтаксис должен быть

{"data.email": "name@example.com"}

Но ваш код генерирует критерии поиска как

{"data":{"email":{"$eq":"name@example.com"}}}

Чтобы это работало, измените строку с

searchData, _ = bson.Marshal(bson.M{"data": bson.M{strings.ToLower(subItemKey): bson.M{"$eq": subItemString}}})

на

searchData, _ = bson.Marshal(bson.M{"data." + strings.ToLower(subItemKey): subItemString})

0 голосов
/ 03 февраля 2019

Я думаю, что вы хотите найти вложенное свойство и, следовательно, вы должны изменить запрос

Это:

searchData, _ =  bson.Marshal(bson.M{"data": bson.M{strings.ToLower(subItemKey): bson.M{"$eq": subItemString}}})

На

nestedKey := fmt.Sprintf("data.%s", strings.ToLower(subItemKey))
searchData, _ = bson.Marshal(bson.M{nestedKey: subItemString})
0 голосов
/ 02 февраля 2019

Я новичок в Golang и у меня нет среды для тестирования, но я думаю, вам следует начать с следующих примеров в Документация MongoDB и изменить

var searchData []uint8
    searchData, _ =  bson.Marshal(bson.M{"data": bson.M{strings.ToLower(subItemKey): bson.M{"$eq": subItemString}}})

на

var searchData bson.D
    searchData = bson.D{{"data." + strings.ToLower(subItemKey), bson.D{{"$eq", subItemString}}}}

Вы определенно должны использовать bison.D, а не bison.M для случая, когда subItemKey пусто, потому что полное совпадение поддокумента, которое вы делаете, не будет выполнено, если поля будут неправильнымиorder.

Для особого случая поиска точного соответствия вы можете использовать упрощенный формат

    searchData = bson.D{{"data." + strings.ToLower(subItemKey), subItemString}}

Возможно, это не решит вашу проблему, но, по крайней мере, будет следовать рекомендуемой схеме.

Если это не исправляет ваш поиск, добавьте к вашему сообщению версии драйвера и базы данных Mongo, которые вы используете, полный документ, который вы ожидаете получить, объявление типа dataStruct иинициализатор для dataStruct, который вы передаете.

...