Декси: Как получить все значения индекса MultiEntry?

У меня есть эти объекты, каждый с массивом тегов:

bookmarks: [
    { url: '...', tags: ['news', 'fun', 'programming'] },
    { url: '...', tags: ['news'] },
    { url: '...', tags: ['fun', 'cooking'] },
    { url: '...', tags: ['hobby', 'fun'] }
]

DB:

const db = new Dexie("bookmarksdb");
db.version(1).stores({
  bookmarks: 'url, *tags'
});

Каким будет лучший (и наиболее производительный) способ получить массив (или набор), содержащий все теги:

['news', 'fun', 'programming', 'cooking', 'hobby']

(есть ли способ получить все значения самого индекса «теги»?)

Изменить: чтобы отобразить «облако тегов» с числами, мне нужно прочитать все теги из таблицы закладок. Так что мне не нужны сами объекты закладок, только их массивы «тегов».


person Wolf359    schedule 21.04.2020    source источник


Ответы (1)


Я бы предложил использовать индекс, чтобы отфильтровать все закладки, содержащие хотя бы один из тегов, а затем отфильтровать его вручную:

const tagsToRequire = ['news', 'fun', 'programming', 'cooking', 'hobby'];
const bookmarksWithFirstTag = await db.bookmarks
  .where({tags: tagsToRequire[0]})
  .toArray();
const bookmarkWithAllTags = bookmarkWithFirstTag.filter(bookmark => tagsToRequire.every(tag => bookmark.tags.includes(tag));

Вы также можете использовать индекс для всех тегов, но нет уверенности, что вы получите лучшую производительность, поскольку для этого потребуется большее количество запросов к БД. С другой стороны, в случае, если первый индекс используется очень часто, а объекты большие, этот второй пример может быть лучше по производительности:

const tagsToRequire = ['news', 'fun', 'programming', 'cooking', 'hobby'];
const keys = await Promise.all(tagsToRequire.map(tag =>
  db.bookmarks.where({tags: tag}).primaryKeys()));
const intersectedKeys = keys.reduce((prev, curr) => prev.filter(key => curr.includes(key)));
const bookmarkWithAllTags = await db.bookmark.bulkGet(intersectedKeys); 

Для этого второго примера также требуется Dexie версии 3.x, в которой есть операция bulkGet ().

person David Fahlander    schedule 21.04.2020
comment
Для «облака тегов» мне нужны все теги (с числами) из всех закладок, вы уже ответили на него здесь. Это фактически отвечает моему второму (более сложному) требованию: пользователи смогут выбирать (переключать) несколько тегов из облака тегов, после чего все закладки с выбранными тегами должны быть возвращены и отображены. Большое спасибо за быстрый ответ! - person Wolf359; 21.04.2020