Deep search question

Okay so I’m trying to search my Users table and it’s new related column called ‘saved’. That saved column contains ColorPalette related objects. Now I’m trying to search for a specific user (With the provided User objectId) and for a specific ColorPalette object inside that ‘saved’ column (With the provided ColorPalette objectId as well). Now I’m using findById function to specify the actual User object ID, and I’m using query to specify ColorPalette objectId that I want to search for, as well. So I want to search for a single ColorPalette object inside ‘saved’ related column of Users table.

However I’m getting a strange result:

Unable to adapt array to data type: class com.example.backendlesstest.domain.model.ColorPalette

This is my function:

    override suspend fun checkSavedPalette(
        userObjectId: String,
        paletteObjectId: String
    ): Users {
        val query = DataQueryBuilder.create()
            .setWhereClause("Users[saved].objectId = '$paletteObjectId'")
            .addRelated("saved")

        return suspendCoroutine { continuation ->
            backendless.of(Users::class.java).findById(
                userObjectId,
                query,
                object : AsyncCallback<Users> {
                    override fun handleResponse(response: Users) {
                        Log.d("BackendlessDataSource", response.saved.colors)
                        continuation.resume(response)
                    }

                    override fun handleFault(fault: BackendlessFault?) {
                        Log.d("BackendlessDataSource", "${fault?.message}")
                        continuation.resume(Users())
                    }
                }
            )
        }
    }

Any suggestions?

Hi @Stefan_Jovanovic ,

Your where clause will be ignored when you call findById method. Only relationsDepth, relationsPageSize, relations will be considered by the server. To perform search you should use find method.

Talking about your error. There can be deviation between your DB scheme and your entity class structure. Can you provide code where you declare your saved column?

Regards, Andriy

I’m trying to find a single ColorPalette object inside a ‘saved’ relational column of Users database table. I have the object id of that ColorPalette that I’m searching for, and also the objectId of the User that holds that ‘saved’ relational data.

ColorPalette:

@Parcelize
data class ColorPalette(
    var objectId: String? = null,
    var approved: Boolean = false,
    var colors: String? = null,
    var totalLikes: Int? = null
) : Parcelable

Users:

@Parcelize
data class Users(
    var id: String? = null,
    var ownerId: String? = null,
    var objectId: String? = null,
    var email: String? = null,
    var saved: ColorPalette? = null
) : Parcelable

Schema

Code

    override suspend fun checkSavedPalette(
        userObjectId: String,
        paletteObjectId: String
    ): List<Users> {
        val query = DataQueryBuilder.create()
            .setWhereClause("Users[saved].objectId = '$paletteObjectId'")
            .setWhereClause("objectId = '$userObjectId'")
            .addRelated("saved")

        return suspendCoroutine { continuation ->
            backendless.of(Users::class.java).find(
                query,
                object : AsyncCallback<List<Users>> {
                    override fun handleResponse(response: List<Users>) {
                        response.forEach {
                            Log.d("BackendlessDataSource", it.toString())
                            Log.d("BackendlessDataSource", it.email)
                            Log.d("BackendlessDataSource", it.saved.colors.toString())
                        }
                        continuation.resume(response)
                    }

                    override fun handleFault(fault: BackendlessFault?) {
                        Log.d("BackendlessDataSource", "${fault?.message}")
                        continuation.resume(emptyList())
                    }
                }
            )
        }
    }

Error:

Unable to adapt array to data type: class com.example.backendlesstest.domain.model.ColorPalette

@Stefan_Jovanovic ,

saved column has 1:N relation. So you need to change type of related field in your entity so it will hold list of palette objects. Error also states about that - SDK can’t convert list of palette objects to single instance of palette.

Also I want to note that by this query you will select user with all palettes. Query states only that user should selected only if among user palettes there is specified one.

Could you please change type of saved field to list and try once more?

Regards, Andriy

But my saved field should be related to my ColorPalette table. Because I already have the logic in my app that adds and removes those items from saved field of Users table.

Add:

    override suspend fun saveColorPalette(
        userObjectId: String,
        colorPaletteObjectId: String
    ): Int? {
        return suspendCoroutine { continuation ->
            val user = Users(objectId = userObjectId)

            backendless.of(Users::class.java).addRelation(
                user,
                "saved",
                arrayListOf(ColorPalette(objectId = colorPaletteObjectId)),
                object : AsyncCallback<Int> {
                    override fun handleResponse(response: Int?) {
                        continuation.resume(response)
                    }

                    override fun handleFault(fault: BackendlessFault?) {
                        continuation.resume(-1)
                    }
                })
        }
    }
Remove
    override suspend fun removeColorPalette(
        userObjectId: String,
        colorPaletteObjectId: String
    ): Int? {
        return suspendCoroutine { continuation ->
            val user = Users(objectId = userObjectId)

            backendless.of(Users::class.java).deleteRelation(
                user,
                "saved",
                arrayListOf(ColorPalette(objectId = colorPaletteObjectId)),
                object : AsyncCallback<Int> {
                    override fun handleResponse(response: Int?) {
                        continuation.resume(response)
                    }

                    override fun handleFault(fault: BackendlessFault?) {
                        continuation.resume(-1)
                    }
                })
        }
    }

@Stefan_Jovanovic ,

The only problem with your entity class is a wrong type for relation field. Your field of type ColorPalette which means that only one palette can be associated with user. But in table there are 1:N relation which means that actually there can be more than one palette. So your field type should also reflect this. Your saved field should be of List<ColorPalette> type.

Regards, Andriy

Ohh, I’ve totally missed that!
I’ve tested it out and now it actually works.

Btw, what I need to do, to get only a single saved color palette, of a single user? I have a user objectId, and a target color palette objectId as well. My current where clause will, as you mention, get all the palettes.

@Stefan_Jovanovic ,

In this case you should query ColorPalette table using reverse relation in query.

Your query to the Color Palette table will look in the next way:
Users[saved].objectId = {user ID} and objectId = {palette ID}

Regards, andriy

1 Like

Reverse relation sounds correct, I’ve just read the docs about it. Thanks Andriy, you’re a lifesaver :slight_smile:

You are welcome!)