How to store and retrieve float array using Couchbase Lite

Hi,
I need to store and retrieve float array that have 1024 value.
I convert float array to string for store to database and retrieve string from database and convert to float array for handling. But it is too slow, performance is too bad.
So, Anyone have other solution for this problem?
I using C++ program. Below is my code:

void Couchbase::creatUserDocument(FLString id, FLString name, FLString feature)
{
    CBLDatabase* db = _pDb;
    char buffer[200];
    snprintf(buffer, sizeof(buffer), "User_%s", (const char*) id.buf);
    FLString db_id = FLStr((const char*)buffer);

    CBLDocument* newTask = CBLDocument_CreateWithID(db_id);
    FLMutableDict properties = CBLDocument_MutableProperties(newTask);
    FLMutableDict_SetString(properties, FLSTR("type"), FLStr("face_info"));
    FLMutableDict_SetString(properties, FLSTR("id"), id);
    FLMutableDict_SetString(properties, FLSTR("name"), name);
    FLMutableDict_SetString(properties, FLSTR("feature"), feature);
    printf("Create Document Sucess\n");

    CBLError err;
    CBLDatabase_SaveDocument(db, newTask, &err);
    CBLDocument_Release(newTask);
}

std::vector<float> Couchbase::convertStringtoFloatArray(std::string str)
{
    // If possible, always prefer std::vector to naked array
    std::vector<float> v;

    // Build an istream that holds the input string
    std::istringstream iss(str);

    // Iterate over the istream, using >> to grab floats
    // and push_back to store them in the vector
    std::copy(std::istream_iterator<float>(iss),
        std::istream_iterator<float>(),
        std::back_inserter(v));
    return v;
}

std::string Couchbase::covertFloatArraytoString(std::vector<float> data)
{
    std::string floatString;

    for (int i = 0; i < FACEDATA_SIZE; i++) {
        floatString.append(std::to_string(data[i]));
        if (i < FACEDATA_SIZE - 1) {
            floatString.append(" ");
        }
    }
    return floatString;
}


//Store float array to database
    std::vector<float> vect;
    for (int i = 0; i < 10000; i++) {
        vect = cbase->generateVectorArray();
        std::string str = cbase->covertFloatArraytoString(vect);
        const char* cstr = str.c_str();
        std::string si = std::to_string(i);
        const char* csi = si.c_str();
        cbase->creatUserDocument(FLStr(csi), FLStr("thang"), FLStr(cstr));
    }

//Retrieve string data and convert to float array
int Couchbase::queryUserFeature(float* ref_feature)
{
    CBLDatabase* db = _pDb;

    CBLError err;

    char queryCmd[128];
    snprintf(queryCmd, sizeof(queryCmd), "SELECT feature FROM `%s` WHERE type = \"face_info\"", qPrintable(_dbConfig.dbName));
    qDebug("%s\n", queryCmd);

    CBLQuery* query = CBLDatabase_CreateQuery(db, kCBLN1QLLanguage, FLStr(queryCmd), NULL, &err);
    CBLResultSet* results = CBLQuery_Execute(query, &err);
    if (!results) {
        qDebug("query result fail!");
        return 0;
    }
    qDebug("query result success!");

    while (CBLResultSet_Next(results)) {
        std::vector<float> resv = {};
        FLString feature = FLValue_AsString(CBLResultSet_ValueForKey(results, FLSTR("feature")));
        std::string ftstr = (const char*)feature.buf;
	    // PROGRAM EXCUTE TOO SLOW IN HERE
        resv = convertStringtoFloatArray(ftstr);
    }
    
    CBLResultSet_Release(results);
    CBLQuery_Release(query);
    return 0;
}

Hi thangnt,

Thank you for your question. I agree storing an array as a string is inefficient and unnecessary. CBL has FLArray and FLMutableArray. You may construct a mutable array via
FLMutableArray_New and FLMutableArray_AppendFloat
and then assign it to the mutable dict by
FLMutableDict_SetArray

Will the above APIs help you?

1 Like

Thank you for your answer!
I stored float array successfully by your guide.

1 Like