Библиотека Javascript для сбора свойств объектов, выполнения пакетной обработки и отображения результатов обратно на объекты - PullRequest
0 голосов
/ 31 мая 2018

Для массива объектов:

[
    {id: 1, name: "test", tagId: 1},
    {id: 2, name: "test", tagId: 15},
    {id: 3, name: "test", tagId: 5},
]

Необходимо сократить список определенных свойств (tagId) до уникального массива [1,15,5], вызвать какой-либо метод пакетной обработки, например, выполнить http-запросдля API для списка сущностей:

async (ids) => await axios.get('http://apihost/tag', {id: ids})

Для массива объектов результатов:

[
    {id: 1, name: "tag1"},
    {id: 15, name: "tag2"},
    {id: 5, name: "tag3"},
]

Наконец, необходимо сопоставить эти объекты по атрибуту ID с исходным массивом объектов, сопоставляемых по result.id=> original.tagId, фактически делает соединение SQL двух массивов, чтобы получить это (например, https://github.com/mtraynham/lodash-joins):

[
    {id: 1, name: "test", tagId: 1, tag: {id: 1, name: "tag1"}},
    {id: 2, name: "test", tagId: 15, tag: {id: 15, name: "tag2"}},
    {id: 3, name: "test", tagId: 5, tag: {id: 5, name: "tag3"}},
]

Я уже написал библиотеку PHP для этого с API, например:

new BulkMap(source).map(
  'tagId',
  'tag',
  async (ids) => axios.get('http://apihost/tag', {id: ids})
);

Но теперь мне нужно это в JS. Есть ли какая-либо библиотека Javascript / NodeJS для этого? Похоже, довольно распространенный шаблон для микросервисов.

Ответы [ 3 ]

0 голосов
/ 31 мая 2018

Функциональный подход.

const { map, uniq } = require('lodash/fp');

const arr = /* you say you already have this */;

const uniqueIds = uniq(map('tagId', arr));
const objects = await axios.get('http://apihost/tag', { id: uniqueIds });
const associated = arr.map(({ id, tagId, name }) => (
  { id, tagId, name, tag: objects.find(o => o.id === tagId) };
));

Если вы хотите индексировать (что может избежать решения O (N ^ 2))

const byTagId = new Map();
arr.forEach(o => byTagId.set(o.tagId, o));
const objects = await axios.get('http://apihost/tag', { id: byTagId.keys() });
const associated = arr.map(({ id, tagId, name }) => (
  { id, tagId, name, tag: byTagId.get(tagId) }
));
0 голосов
/ 31 мая 2018

Мне нравится решение @RiverTam https://stackoverflow.com/a/50629965/962746. Единственное, что нужно исправить: несколько объектов в исходном массиве могут иметь один и тот же tagId, поэтому я являюсь объектами ответа индекса вместо исходных объектов:

const lodashUniq = require('lodash.uniq');
const lodashMap = require('lodash.map');

const source = [
    {id: 1, name: "test", tagId: 1},
    {id: 2, name: "test", tagId: 15},
    {id: 3, name: "test", tagId: 5},
];

const uniqueIds = lodashUniq(lodashMap(source, 'tagId'));
const tags = await axios.get('http://apihost/tag', { id: uniqueIds });

const tagsIndex = new Map(tags.map(tag => [tag.id, tag]));
const result = source.map(s => (
    {... s, tag: tagsIndex.get(s.tagId)}
));
0 голосов
/ 31 мая 2018

Интересно. Вот моя попытка.

const inits = [
    {id: 1, name: "test", tagId: 1},
    {id: 2, name: "test", tagId: 15},
    {id: 3, name: "test", tagId: 5},
];

// Get all ids
const ids = inits.map(init => init.tagId);

const results = [
    {id: 1, name: "tag1"},
    {id: 15, name: "tag2"},
    {id: 5, name: "tag3"},
];

// Add results to object
const final = inits.map(init => {
    init.tag = results.find(res => res.id === init.tagId);
    return init;
});

[Обновлено]

Если вы можете быть уверены, что порядок объектов останется прежним, вы можете ускорить его:

// Add results to object
const final = inits.map((init, index) => {
    init.tag = results.[index];
    return init;
});

Почему JavaScript такой сексуальный: (* ​​1009 *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...