Перейти к основному содержимому

Lookup

Поле типа Lookup автоматически получает значение поля из связанной записи.

Основные характеристики

  • Тип данных: Зависит от исходного поля
  • Источник: Поле из связанной записи
  • Режим: Только для чтения
  • Обновление: Автоматическое при изменении связанной записи
  • Множественные значения: Поддержка массивов при множественных связях

Как работает Lookup

Lookup позволяет "подтянуть" значение поля из связанной записи без необходимости делать дополнительные запросы.

Заказ → Клиент → Email клиента

Вместо того чтобы делать два запроса (получить заказ, затем клиента), Lookup автоматически получает email клиента в записи заказа.

Настройки поля

При создании поля типа "Lookup" доступны следующие настройки:

  • Название поля: Отображаемое имя поля
  • Системное имя: Уникальный идентификатор для API
  • Описание: Подсказка для пользователей
  • Поле связи: Поле типа Relation в текущей коллекции
  • Поле для получения: Поле из связанной записи
  • Множественные значения: Если связь множественная (One-to-Many)

Примеры использования

Email клиента в заказе

{
"name": "customer_email",
"type": "lookup",
"relationField": "customer",
"lookupField": "email"
}

Структура:

  • Коллекция orders имеет поле customer (Relation → users)
  • Lookup customer_email получает email из связанного пользователя

Название категории в товаре

{
"name": "category_name",
"type": "lookup",
"relationField": "category",
"lookupField": "name"
}

Имя автора в статье

{
"name": "author_name",
"type": "lookup",
"relationField": "author",
"lookupField": "full_name"
}

Цены товаров в заказе

{
"name": "item_prices",
"type": "lookup",
"relationField": "items",
"lookupField": "price",
"multiple": true
}

Работа через API

Получение значения Lookup

const order = await emd.database.collection('orders').get(orderId);

console.log(order.customer_email); // "customer@example.com"
console.log(order.customer_name); // "Иван Иванов"

Множественные значения

const order = await emd.database.collection('orders').get(orderId);

console.log(order.item_names);
// ["Ноутбук Dell XPS 15", "Мышь Logitech", "Клавиатура"]

console.log(order.item_prices);
// [89990, 1990, 3990]

Поиск по Lookup полю

// Найти заказы клиента с определенным email
const orders = await emd.database.collection('orders').find({
customer_email: 'customer@example.com'
});

// Найти товары определенной категории
const products = await emd.database.collection('products').find({
category_name: 'Электроника'
});

Вложенные Lookup

Lookup из вложенной связи

{
"name": "customer_city",
"type": "lookup",
"relationField": "customer",
"lookupField": "address.city"
}

Структура:

  • orders.customerusers
  • users.address → JSON поле с city
  • Lookup получает city из адреса клиента

Цепочка Lookup

// В коллекции orders
{
"name": "customer_manager_name",
"type": "lookup",
"relationField": "customer",
"lookupField": "manager.name"
}

Структура:

  • orders.customercustomers
  • customers.managerusers
  • Lookup получает имя менеджера клиента

Примеры со сложными структурами

Информация о товарах в заказе

// Коллекция: orders
// Поля:
// - items: Relation (Many) → products
// - item_names: Lookup → items.name
// - item_prices: Lookup → items.price
// - item_images: Lookup → items.image

const order = await emd.database.collection('orders').get(orderId);

console.log(order.item_names);
// ["Товар 1", "Товар 2", "Товар 3"]

console.log(order.item_prices);
// [1000, 2000, 3000]

Данные автора статьи

// Коллекция: articles
// Поля:
// - author: Relation → users
// - author_name: Lookup → author.name
// - author_email: Lookup → author.email
// - author_avatar: Lookup → author.avatar

const article = await emd.database.collection('articles').get(articleId);

console.log(`Автор: ${article.author_name}`);
console.log(`Email: ${article.author_email}`);

Комбинация с формулами

Полная информация о клиенте

{
"name": "customer_info",
"type": "formula",
"formula": "`${record.customer_name} (${record.customer_email})`",
"resultType": "string"
}

Где customer_name и customer_email — это Lookup поля.

Общая стоимость товаров

{
"name": "items_total",
"type": "formula",
"formula": "record.item_prices.reduce((sum, price) => sum + price, 0)",
"resultType": "number"
}

Где item_prices — это Lookup поле с множественными значениями.

Обновление Lookup полей

Lookup поля обновляются автоматически при изменении связанной записи:

// Изменить email клиента
await emd.database.collection('users').update(customerId, {
email: 'newemail@example.com'
});

// Все заказы этого клиента автоматически получат новый email в customer_email
const order = await emd.database.collection('orders').get(orderId);
console.log(order.customer_email); // "newemail@example.com"

Производительность

Преимущества Lookup

  • Не требует дополнительных запросов
  • Автоматическое обновление при изменении источника
  • Удобство использования в интерфейсе

Недостатки

  • Увеличивает размер документа
  • Может замедлить запись при большом количестве Lookup полей

Оптимизация

// Получить только нужные поля
const order = await emd.database.collection('orders').get(orderId, {
fields: ['customer_name', 'customer_email', 'total']
});

Индексация

// Создать индекс для Lookup поля
await emd.database.collection('orders').createIndex({
customer_email: 1
});

Типичные сценарии

CRM: Информация о компании в контакте

{
"name": "company_name",
"type": "lookup",
"relationField": "company",
"lookupField": "name"
},
{
"name": "company_industry",
"type": "lookup",
"relationField": "company",
"lookupField": "industry"
}

E-commerce: Данные товара в позиции заказа

{
"name": "product_name",
"type": "lookup",
"relationField": "product",
"lookupField": "name"
},
{
"name": "product_price",
"type": "lookup",
"relationField": "product",
"lookupField": "price"
},
{
"name": "product_image",
"type": "lookup",
"relationField": "product",
"lookupField": "main_image"
}

Проекты: Участники команды

{
"name": "team_member_names",
"type": "lookup",
"relationField": "team_members",
"lookupField": "name",
"multiple": true
},
{
"name": "team_member_emails",
"type": "lookup",
"relationField": "team_members",
"lookupField": "email",
"multiple": true
}

Отображение в интерфейсе

Простое значение

const order = await emd.database.collection('orders').get(orderId);

console.log(`Клиент: ${order.customer_name}`);
console.log(`Email: ${order.customer_email}`);

Множественные значения

const order = await emd.database.collection('orders').get(orderId);

const itemsList = order.item_names.map((name, index) => `
<li>${name} - ${order.item_prices[index]} ₽</li>
`).join('');

console.log(`<ul>${itemsList}</ul>`);

Ограничения

  • Нельзя делать Lookup из Lookup (только один уровень вложенности)
  • Максимальная глубина вложенности: 2 уровня (relation.field.subfield)
  • Lookup поля нельзя редактировать напрямую
  • При удалении связанной записи Lookup становится null

Рекомендации

  • Используйте Lookup для часто используемых полей из связанных записей
  • Не создавайте слишком много Lookup полей (влияет на производительность)
  • Используйте Lookup вместо populate для простых случаев
  • Создавайте индексы для Lookup полей, по которым часто ищете
  • Документируйте структуру связей и Lookup полей

Отличие от других типов

  • Lookup vs Formula: Lookup получает значение из связанной записи, Formula вычисляет
  • Lookup vs Rollup: Lookup для одного значения, Rollup для агрегации множества
  • Lookup vs Relation: Lookup показывает конкретное поле, Relation показывает всю запись