Ios swift queries with arrays containing objects

Yeah, the underlying query syntax in Couchbase Lite Core uses a few ‘magic’ property names like _id, _sequence, etc. to represent metadata. When you query a real property with such a name, it gets confused with one of those.

I could add a way to escape the underscore. But even if I do, you’re going to run into problems when you try syncing with a server, because Sync Gateway has a very hard restriction against any top-level property starting with “_” … and this restriction is tied up with its REST API and couldn’t be relaxed without making significant changes to that API, i.e. not gonna happen.

I can’t imagine that this process is automatic. Isn’t there a chance for you to intercept and rename these things?

we are not using sync gateway or rest api, so that would work for us. And it is not a top-level property.

Huh — an underscore prefix should not be a problem if it’s not a top-level property. Could you show me a sample of what the docs look like, and a query that fails?

{
   "type: "product",
     "claims" : [
           { "_id": { "$oid": "56c20025533f4c14e4000799"}},
           { "_id": { "$oid": "56c20027533f4c14e40007af"}}
       ]
}
{
 "_id": {
       "$oid": "56c20025533f4c14e4000799"
    },
  "type": "label"
}

almost same query as above, except:
ArrayExpression.any(ArrayExpression.variable(“d”))
.in(Expression.property(“claims”).from(“p”))
.satisfies(ArrayExpression.variable(“d._id.$oid”)).equalTo(Expression.property("_id.$oid").from(“l”))
.and(Expression.property(“type”).from(“p”).equalTo(Expression.string(“product”))
.and(Expression.property(“type”).from(“l”).equalTo(Expression.string(“label”))))

Since we are using the id (inside the _id.$oid) as CB object id (i.e. Meta.id), then we can replace Expression.property("_id.$oid").from(“l”) by Meta.id.from(“l”) in above. However, the issue is the embedded claims[] with {"_id": { “$oid”: “…”}} where the _ is causing the problem in the ArrayExpression.variable(“d._id.$oid”)

This is a top level _id property.

“we can replace Expression.property(”_id.$oid").from(“l”) by Meta.id.from(“l”) in above." but the other one is not.

I didn’t expect that it would work, given that Couchbase Lite IDs are strings, not dictionaries. @jens Could it be that the _ operator is not respecting top level vs non top level? Is there even a way that we can give it that information?

What Jim said — “This is a top level _id property.” It doesn’t matter that some of the documents have nested _id properties; the actual problem is the documents that have _id at the top level.

so If I remove the _id: $oid at the top level of documents and only use Meta.id, then that would work? For example:

{
   "type: "product",
     "claims" : [
           { "_id": { "$oid": "56c20025533f4c14e4000799"}},
           { "_id": { "$oid": "56c20027533f4c14e40007af"}}
       ]
}

(Meta.id = "56c20025533f4c14e4000799")
{
    },
  "type": "label"
}

then:
ArrayExpression.any(ArrayExpression.variable(“d”))
.in(Expression.property(“claims”).from(“p”))
.satisfies(ArrayExpression.variable(“d._id.$oid”)).equalTo(Meta.id).from(“l”))
.and(Expression.property(“type”).from(“p”).equalTo(Expression.string(“product”))
.and(Expression.property(“type”).from(“l”).equalTo(Expression.string(“label”))))

would that work? (Just removing the top level _id:$oid would be simple for me, instead of going deep to all the instances in all objects)

Yes, the usual way to link/join to another document is to use its document ID.

To be clear here, you would remove the top level _id and then save the document using that string as its ID. This is a key part. Meta.id is not a property key, but a shortcut in the query builder to getting the document ID from a document the database. The way to set the document ID is by creating a mutable document with that ID and then saving it. Not sure if that point got across or not.

I’ve been doing exactly that. Now, I just removed the top level “_id”. My final question is if there are “_id” embedded inside properties, would the ArrayExpression.variable(“d._id.$oid”) in a join statement work?

Yes, it should work fine.