couchbase, how to match the entire sub document

142 Views Asked by At

Here are example records in couchbase

{
  a: "iama",
  b: {
    c: "iamc",
    d: "iamd",
  },
  f: "iamf"
  // ... other properties we don't care about

}

{
  a: "iama",
  b: {
    c: "iamc",
    d: "iamd"
  },
  f: "iamnotf"
  // ... other properties we don't care about

}

And I want to find records where the entire object of b matches, but it's not certain what b contains.

I'm using ottomanjs, and here is my attempt. I think it's ugly.

    const arr = [];
    Object.keys(b).forEach((key) => {
      const k = `b.${key}`;
      arr.push({ [k]: b[key] });
    });

    model.find({ $and: arr });

so in the example above the filter looks like this:

{
  "$and": [
    {
      "b.c": "iamc"
    },
    {
      "b.d": "iamd"
    }
  ]
}

it will convert that filter into the n1ql query like this:

SELECT * FROM `table` WHERE ( b.c="iamc" AND b.d="iamd") AND _type="model..."

This is only a half solution because I am assuming every property of b is not a nested object. But of course, I can have a recursive function to construct the filter.

Maybe another way is to process everything in memory. utilizing JSON.stringify(b1) == JSON.stringfy(b2) or _.isEqual(b1, b2)

I'm almost certain that this is not the best practice. any advice? or just another approach.


**other info

What if I want all records to have a unique b field? I can use the stringify version of b as the key to the document. So when trying to look up b, I just search by document id. Can't do that with ottoman, but possible with the couchbase sdk

1

There are 1 best solutions below

1
On

Just do WHERE b1 = b2. It does Json comparison fieldd names, value including type of value, in case array position, recursively nested info. encode_josn() is stringfy.

The following example gives one document other did not match.

SELECT t 
FROM [{ "a": "iama", 
        "b":  { "c": "iamc", "d": "iamd" },
        "b1": { "c": "iamc", "d": "iamd" } }, 
      { "a": "iama", 
        "b":  { "c": "iamc", "d": "iamd" }, 
        "b1": { "c1": "iamc", "d": "iamd" } }
      ] AS t 
WHERE t.b = t.b1;

{
    "results": [
    {
        "t": {
            "a": "iama",
            "b": {
                "c": "iamc",
                "d": "iamd"
            },
            "b1": {
                "c": "iamc",
                "d": "iamd"
            }
        }
    }
    ]
}

https://docs.couchbase.com/server/current/n1ql/n1ql-language-reference/datatypes.html#collation