thekid / dialog

Dialog photoblog
2 stars 1 forks source link

Include location names for autocompletion #30

Closed thekid closed 1 year ago

thekid commented 1 year ago

Change

Before:

Before

After:

After

The precedence is as follows:

  1. Direct matches in the title
  2. Journeys with matches in the locations field
  3. Other content with matches in the locations field

Implementation

As autocomplete does not work on arrays or documents inside arrays (which is what the locations field consists of), we need to create an extra string field for this purpose. We already have our special _searchable member, so we add it there.

Migration

Run this script once on the current database:

use com\mongodb\MongoConnection;
use util\cmd\Console;

$conn= new MongoConnection('mongodb+srv://[user]:[pass]@dialog.[id].mongodb.net/');
$collection= $conn->collection('dialog.entries');
foreach ($collection->find() as $entry) {
  Console::writeLine('> ', $entry['title']);

  // Create _searchable.suggest
  $suggest= '';
  foreach ($entry['locations'] as $location) {
    $suggest.= ' '.$location['name'];
  }

  $collection->update($entry->id(), ['$set' => [
    '_searchable' => $entry['_searchable'] + ['suggest' => trim($suggest)]
  ]]);
}

Index definition

This is how the search index needs to be defined in MongoDB Atlas:

{
  "mappings": {
    "dynamic": true,
    "fields": {
      "_searchable": {
        "dynamic": true,
        "fields": {
          "suggest": [{"dynamic": true, "type": "document"}, {"type": "autocomplete"}]
        },
        "type": "document"
      },
      "date": [{"dynamic": true, "type": "document"}, {"type": "date"} ],
      "title": [{"dynamic": true, "type": "document"}, {"type": "string"}, {"type": "autocomplete"}]
    }
  }
}

Note: The _searchable.dynamic key is important for the thing to work - unfortunately, the visual editor does not let you edit it like that!

thekid commented 1 year ago

Released in https://github.com/thekid/dialog/releases/tag/v1.8.0