chromadb-java-client icon indicating copy to clipboard operation
chromadb-java-client copied to clipboard

Where and Where_document syntax

Open byflostter33 opened this issue 1 year ago • 8 comments

Unable to use Where and Where_document because in code it's just Map<String,String> but in the documentation it's something like: { "metadata_field": { "$nin": ["value1", "value2", "value3"] } }

Can you provide example how to use them from the library?

byflostter33 avatar Sep 06 '23 08:09 byflostter33

@byflostter33, apologies for that oversight. $in, $nin was rolled out with 0.4.9 last night, so I haven't had a chance to catch up :).

Can you do a PR for this, or just wait a day or two for me to get to this?

tazarov avatar Sep 06 '23 09:09 tazarov

it's fine for me to wait

actually I'm looking for something like ' please give me all documents that not in list of id (1,2,3) '

byflostter33 avatar Sep 06 '23 09:09 byflostter33

@byflostter33, is it safe to assume that this list of Ids you mentioned above is stored in metadata?

tazarov avatar Sep 06 '23 10:09 tazarov

image

byflostter33 avatar Sep 06 '23 10:09 byflostter33

Gotcha. Well that is a bit of a different case of filtering. By default when you use query/get you can specify which Ids you want but not invert.

As a workaround, you can consider adding IDs in the metadata. But ideally, you shouldn't care about Ids unless it is about updating/deleting documents. Try to figure out a strategy that involves metadata as opposed to IDs.

tazarov avatar Sep 06 '23 10:09 tazarov

okay,

due to I need more filtering like ids but not only them - will wait for $in $nin

From my perspective - it's better use not Map<String,String> but something more complex - to haveability to create any type of criteria of search for where and where_document cases

byflostter33 avatar Sep 06 '23 10:09 byflostter33

Hey, I need Where builder, I saw your overhaul(0.2.0) branch. How can I use the filter operator with the current version (0.1.5)?

sonic-onkaringale avatar May 30 '24 15:05 sonic-onkaringale

I made a workaround in Kotlin

class WhereBuilder private constructor()
{
    private val filter = JsonObject()

    fun eq(field: String, value: Any): WhereBuilder
    {
        return operation("\$eq", field, value)
    }

    fun gt(field: String, value: Any): WhereBuilder
    {
        return operation("\$gt", field, value)
    }

    fun gte(field: String, value: Any): WhereBuilder
    {
        return operation("\$gte", field, value)
    }

    fun lt(field: String, value: Any): WhereBuilder
    {
        return operation("\$lt", field, value)
    }

    fun lte(field: String, value: Any): WhereBuilder
    {
        return operation("\$lte", field, value)
    }

    fun ne(field: String, value: Any): WhereBuilder
    {
        return operation("\$ne", field, value)
    }

    fun `in`(field: String, value: List<Any?>): WhereBuilder
    {
        return operation("\$in", field, value)
    }

    fun nin(field: String, value: List<Any?>): WhereBuilder
    {
        return operation("\$nin", field, value)
    }

    fun and(vararg builders: WhereBuilder): WhereBuilder
    {
        val jsonArray = JsonArray()
        for (builder in builders)
        {
            jsonArray.add(builder.filter)
        }
        filter.add("\$and", jsonArray)
        return this
    }

    fun or(vararg builders: WhereBuilder): WhereBuilder
    {
        val jsonArray = JsonArray()
        for (builder in builders)
        {
            jsonArray.add(builder.filter)
        }
        filter.add("\$or", jsonArray)
        return this
    }

    private fun operation(operation: String, field: String, value: Any): WhereBuilder
    {
        val innerFilter = JsonObject()
        if (value is List<*>)
        {
            val jsonArray = JsonArray()
            for (o in value)
            {
                if (o is String) jsonArray.add(o.toString())
                else if (o is Int) jsonArray.add(o)
                else if (o is Float) jsonArray.add(o)
                else if (o is Boolean) jsonArray.add(o)
                else
                {
                    throw IllegalArgumentException("Unsupported type: " + if (o == null) "null" else o::class.java)
                }
            }
            innerFilter.add(operation, jsonArray)
        }
        else
        {
            innerFilter.addProperty(operation, value.toString())
        }
        filter.add(field, innerFilter) // Gson handles various value types
        return this
    }

    fun build(): JsonObject
    {
        return filter
    }

    companion object
    {
        fun create(): WhereBuilder
        {
            return WhereBuilder()
        }
    }
}

class WhereDocumentBuilder private constructor()
{
    private val filter = JsonObject()

    fun contains(value: String): WhereDocumentBuilder
    {
        return operation("\$contains", value)
    }

    fun notContains(value: String): WhereDocumentBuilder
    {
        return operation("\$not_contains", value)
    }

    fun and(vararg builders: WhereDocumentBuilder): WhereDocumentBuilder
    {
        val jsonArray = JsonArray()
        for (builder in builders)
        {
            jsonArray.add(builder.filter)
        }
        filter.add("\$and", jsonArray)
        return this
    }

    fun or(vararg builders: WhereDocumentBuilder): WhereDocumentBuilder
    {
        val jsonArray = JsonArray()
        for (builder in builders)
        {
            jsonArray.add(builder.filter)
        }
        filter.add("\$or", jsonArray)
        return this
    }

    private fun operation(operation: String, value: Any): WhereDocumentBuilder
    {
        filter.addProperty(operation, value.toString()) // Gson handles various value types
        return this
    }

    fun build(): JsonObject
    {
        return filter
    }

    companion object
    {
        fun create(): WhereDocumentBuilder
        {
            return WhereDocumentBuilder()
        }
    }
}


fun Collection.queryElite(
    emF: EmbeddingFunction,
    queryTexts: List<String?>?,
    nResults: Int?,
    where: JsonObject?,
    whereDocument: JsonObject?,
    include: List<IncludeEnum?>?
): QueryResponse?
{
    val apiClient = ApiClient()
    var api: DefaultApi? = null
    val body = QueryEmbedding()
    apiClient.setBasePath("http://localhost:8000")
    api = DefaultApi(apiClient)
    apiClient.setHttpClient(
        apiClient.httpClient.newBuilder().readTimeout(60, TimeUnit.SECONDS).writeTimeout(60, TimeUnit.SECONDS).build()
    )
    api.apiClient.setUserAgent("Chroma-JavaClient/0.1.x")

    body.queryEmbeddings(emF.createEmbedding(queryTexts) as List<Any?>)
    body.nResults(nResults)
    body.include(include)
    if (where != null)
    {
        body.where(
            where.asMap() as Map<String, Any>?
        )
    }
    if (whereDocument != null)
    {

        body.whereDocument(whereDocument.asMap() as Map<String, Any>?)
    }
    val gson = Gson()
    val json = gson.toJson(api.getNearestNeighbors(body, this.id))
    return Gson().fromJson(json, QueryResponse::class.java)

}

sonic-onkaringale avatar May 30 '24 18:05 sonic-onkaringale