How to use objects (hash/multidimensional array) as Swiftype values

How to use objects (hash/multidimensional array) as Swiftype values

One of the quirks of Swiftype is that you can’t really have a multidimensional array indexed. I mean you could (by using json_encoded) but you couldn’t use it for search & filters.

On the bright side, you can use flat arrays, so yay!

So my particular usecase consists in having a location field that’s an array of arrays. Basically my field content looks like this (this is PHP but can be applied to any language):

[
  [
    "state": "NY",
    "province": "Bronx"
  ],
  [
    "state": "Alaska",
    "province": "South Central"
  ],
  [
    "state": "Alaska",
    "province": "Far North"
  ],
]

Ok, so how can we store this in a way that’s also searchable?

One way is to ditch the location field and split it into state and province fields. Now we can feed each fields with flatten arrays, something like:

"state": ["Alaska", "New York"],
"province": ["Bronx", "South Central", "Far North"]

But it’s pretty obvious that now we have a problem: How do we know which is which? Is Alaska & Bronx? New York & Far North?

My aproach was to flatten these into a simple array (there is a small caveat: you can’t use this for filtering out of the box; but that’s another can of worms, that’s a problem for a future me!).

So instead of previous object, we now have:

"location": [
  "0:state: NY",
  "0:province: Bronx",
  "1:state: Alaska",
  "1:province: South Central",
  "2:state: Alaska",
  "2:province: Far North",
]

Also the code is fairly simple:

function flattenObject(array $obj): array
    {
        $flat = [];
        foreach ($obj as $index => $item) {
            foreach ($item as $key => $value) {
                $flat[] = sprintf("%d:%s: %s", $index, $key, $value);
            }
        }

        return $flat;
    }

But how do you unflat this bad boy?

function unflattenObject(array $obj): array
    {
        $unflatten = [];

        foreach ($obj as $item) {
            preg_match('/^(\d+):([^:]+):(\s.*$)/', $item, $matches);

            if (count($matches) !== 4) {
                continue;
            }

            $matches = array_map('trim', $matches);
            $unflatten[$matches[1]][$matches[2]] = $matches[3];
        }

        return $unflatten;
    }

There are some caveats though:

  1. As I mentioned before, this kind of mess up the facets. It might be fixable, but for me is not really a priority right now;
  2. Array keys should not have : within them.

Now, if you want to search through a specific field, you would just use something like state: NY.

I know, it’s kind of a dirty approach, but hey, ain’t stupid if it works, right?

Adaugă un comentariurăspuns pentru

Poți adăuga bucăți de cod folosind [code]codul tău aici[/code], [js][/js], [php][/php] etc.

Link-urile în context sunt binevenite. Comentariile fără nume/email valid sunt șterse.
PS: Comentariul NU este editabil.

Acest sit folosește Akismet pentru a reduce spamul. Află cum sunt procesate datele comentariilor tale.

Site-ul blog.iamntz.com utilizează cookie-uri. Continuarea navigării presupune acceptarea lor. Mai multe informații.

windows apple dropbox facebook twitter