МАТЧАСТЬ / KNOWLEDGE GRAPH / DOCUMENT 19 / 02.09.2026
Entity Graph и модель данных «Матчасти»
Как хранить компании, юридические лица, бренды, экспертов, продукты, темы, публикации, источники и связи между ними так, чтобы одна база одновременно обслуживала публичное медиа, верификацию, structured data, поиск, AI Visibility, рекомендации, историю изменений и будущий агентский кабинет.
Entity ≠ Pageобъект данных существует независимо от публичного URL
Claim ≠ Factутверждение хранит источник, время и статус проверки
PostgreSQLфизическое хранилище MVP; graph semantics поверх relational model
Temporalсвязи и факты должны уметь иметь начало, конец и историю
1. Главное решение
Строить логический knowledge graph, но не начинать проект с отдельной graph database. На MVP достаточно PostgreSQL: отдельные таблицы сущностей, идентификаторов, утверждений, связей, источников и версий. pgvector использовать для entity resolution, семантического поиска и рекомендаций, а не как замену нормальной модели данных.
LOGICAL MODEL:
KNOWLEDGE GRAPH
PHYSICAL MVP:
PostgreSQL
├─ entities
├─ organizations
├─ persons
├─ brands
├─ publications
├─ topics
├─ identifiers
├─ names / aliases
├─ relations / edges
├─ claims
├─ sources
├─ verification
├─ versions
└─ embeddings (pgvector)
НЕ НУЖНО НА MVP:
Neo4j только потому, что слово "graph" звучит красиво.
2. Базовый принцип: сущность, утверждение, источник
Wikidata представляет знания через statements вида subject → predicate → object и позволяет добавлять qualifiers, например время действия связи. W3C PROV отдельно подчёркивает provenance: происхождение данных, агента, активность и историю формирования объекта. Для «Матчасти» эти два принципа объединяются.
ENTITY
Компания X
CLAIM
Компания X — основана — 2022
SOURCE
официальный реестр / сайт / документ
PROVENANCE
кто добавил
когда извлечено
когда проверено
какая версия источника
какой verification status
Мы не должны хранить важный факт просто как колонку, происхождение которой забыто. Для поисковой/AI-видимости ценность «Матчасти» будет именно в способности объяснить, откуда взялась информация.
3. Entity ≠ Public Page
| Объект | Может существовать в БД? | Обязан иметь URL? |
| Юридическое лицо | Да | Нет |
| Бренд | Да | Нет |
| Продукт | Да | На MVP нет массовых product pages |
| Компания/организация с достаточной value | Да | Да при index eligibility |
| Эксперт | Да | Только при публичной ценности/согласованном профиле |
| Topic | Да | Только curated/indexable state |
| Source URL | Да | Не создавать публичную страницу автоматически |
Это защищает IA от тонких автоматических страниц и позволяет сначала накопить граф, а потом решать, что публиковать.
4. Core entity types
| Entity type | Что представляет | MVP |
| ORGANIZATION | Организация как реальный экономический/общественный субъект | Да |
| LEGAL_ENTITY | Конкретное зарегистрированное юридическое лицо/ИП | Да |
| BRAND | Бренд, который может принадлежать организации или использоваться несколькими юрлицами | Да |
| PERSON | Эксперт, сотрудник, основатель, автор | Да |
| PRODUCT | Программный/физический продукт | Хранить, но без массового публичного каталога |
| SERVICE | Услуга/направление бизнеса | Хранить |
| TOPIC | Концепт/тема knowledge graph | Да |
| INDUSTRY | Устойчивая бизнес-классификация | Да |
| PUBLICATION | Article / Case / Research / News / Interview | Да |
| SOURCE | Документ, URL, dataset, реестр, официальный материал | Да |
| CAMPAIGN | Коммерческая/измерительная кампания | После коммерческого MVP |
5. Почему Organization, Legal Entity и Brand нельзя слить
Schema.org отдельно различает Organization и Brand; Google Organization markup также различает display name и legalName, а идентификаторы могут использоваться для disambiguation.
ПРИМЕР:
"CloudWorks" ← BRAND
ООО "Клауд Воркс" ← LEGAL_ENTITY RU
CloudWorks Ltd ← LEGAL_ENTITY UK
CloudWorks Group ← ORGANIZATION / GROUP
relations:
BRAND OWNED_BY Organization
LegalEntity PART_OF Organization
LegalEntity OPERATES Brand
Organization HAS_LEGAL_ENTITY ...
На сайте читателю можно показать одну удобную "Company Page",
но в данных эти объекты не должны сливаться.
6. Canonical entity ID
Каждая сущность получает неизменный внутренний UUID. Название, slug, бренд и юридический статус могут меняться; entity_id остаётся.
entity_id = UUID
entity_type
status
created_at
updated_at
merged_into_id
visibility_state
index_state
Public slug никогда не используется как primary key.
7. Идентификаторы
OpenCorporates строит идентификацию компаний на паре jurisdiction + company number. Google Organization markup поддерживает реальные business identifiers и отдельно рекомендует identifier-поля для disambiguation. Для России «Матчасть» должна хранить локальные идентификаторы отдельно, а не в одной строке «ИНН/ОГРН».
| Тип | Пример | Уникальность |
| INN | 7701234567 | В рамках юрисдикции/типа |
| OGRN | 1027700... | Россия |
| KPP | ... | Не самостоятельный global identity |
| Company register number | 12345678 | + jurisdiction |
| LEI | ISO 17442 identifier | Глобальный |
| GLN | GS1 | Глобальный при применимости |
| Official domain | example.com | Сильный signal, но ownership меняется |
| Wikidata ID | Q... | External same-entity mapping |
8. Таблица identifiers
entity_identifiers
id
entity_id
scheme // INN, OGRN, LEI, DOMAIN, WIKIDATA...
value
jurisdiction
normalized_value
is_primary
verification_status
valid_from
valid_to
source_id
created_at
Идентификатор сам тоже имеет provenance. Например, domain может быть подтверждён DNS/email сегодня, но через два года сменить владельца.
9. Названия и aliases
entity_names
entity_id
name
name_type:
DISPLAY
LEGAL
BRAND
ALIAS
PREVIOUS_NAME
TRANSLITERATION
SHORT
language
valid_from
valid_to
source_id
is_preferred
Это позволит нормально решать rebranding, исторические имена, транслитерации и entity matching.
10. Не хранить «бывшее название» в одном текстовом поле
Исторические имена нужны search/AI/entity resolution. Их нельзя стирать при обновлении профиля.
2022–2025:
"OldBrand"
2025–:
"NewBrand"
search:
OldBrand → resolves same entity
public page:
NewBrand
"ранее OldBrand"
11. Relations / edges
| Relation type | From | To |
| EMPLOYED_BY | Person | Organization |
| FOUNDER_OF | Person | Organization |
| OWNS_BRAND | Organization | Brand |
| OPERATES_BRAND | LegalEntity | Brand |
| PART_OF_GROUP | Organization/LegalEntity | Organization |
| SUCCESSOR_OF | Organization | Organization |
| OFFERS | Organization | Product/Service |
| ABOUT | Publication | Any entity |
| AUTHOR | Person | Publication |
| SPONSOR_OF | Organization | Publication/Research |
| CLIENT_IN_CASE | Organization | Publication |
| VENDOR_IN_CASE | Organization | Publication |
| RELATED_TOPIC | Topic | Topic |
| BELONGS_TO_INDUSTRY | Organization | Industry |
12. Каждая связь должна быть временной
Wikidata использует qualifiers вроде start time/end time для отношений. Для «Матчасти» это критично: сотрудник, владелец бренда или статус компании меняются.
entity_relations
subject_entity_id
predicate
object_entity_id
valid_from
valid_to
status:
CLAIMED
VERIFIED
DISPUTED
HISTORICAL
source_id
confidence
created_by
verified_by
created_at
updated_at
Не переписывать «Иван работает в X» на «Иван работает в Y». Закрыть первую связь датой и создать вторую.
13. Claim ≠ Fact
В контентной платформе часть данных поступает от самой компании, часть — из реестров, часть — из редакции. Поэтому любое утверждение проходит состояние.
CLAIM STATES
UNVERIFIED
→ SOURCE_ATTACHED
→ VERIFIED
альтернативы:
DISPUTED
REJECTED
EXPIRED
SUPERSEDED
| Пример | Как хранить |
| «Компания обслуживает 15 000 клиентов» | Claim + source + as_of date, не вечный факт |
| «ОГРН = ...» | Identifier verified against registry |
| «Лидер рынка» | Не превращать в verified fact без прозрачного критерия |
| «Основана в 2018» | Claim / attribute with provenance |
14. Facts vs claims в физической модели
Не нужно превращать каждое простое поле в сложный RDF triple. MVP должен оставаться практичным.
Typed core columns
Часто используемые стабильные поля: entity_id, type, display_name, status, canonical domain reference.
Claims table
Изменяемые/оспоримые/источниковые данные: employee count, revenue claim, client count, awards, historical facts и т. д.
То есть модель гибридная: relational core + provenance-aware claims.
15. Provenance
W3C PROV рассматривает provenance как информацию об объектах, действиях и агентах, участвовавших в создании данных. «Матчасть» не обязана реализовывать PROV-O буквально, но должна перенять его логику.
PROVENANCE RECORD
what:
claim / relation / publication / asset
source:
URL / document / registry / interview / client form
activity:
import / edit / verification / moderation / extraction
agent:
client user
editor
system
AI worker
external registry
time:
observed_at
verified_at
valid_from / valid_to
version:
source snapshot / checksum
16. Source entity
sources
source_id
source_type:
OFFICIAL_REGISTRY
OFFICIAL_SITE
DOCUMENT
MEDIA
RESEARCH
INTERVIEW
USER_SUBMISSION
API
OTHER
publisher_entity_id
title
url
published_at
retrieved_at
archive_reference
content_hash
trust_tier
metadata_json
17. Source ≠ citation text
Один источник может подтверждать несколько claims и использоваться в нескольких публикациях. Поэтому источник хранится отдельной сущностью, а citation в статье ссылается на source_id.
Source S1
"Годовой отчёт X"
supports:
Claim 12 revenue
Claim 14 employee count
Research publication 44
Company profile 9
18. Trust tiers для источников
| Tier | Тип | Пример |
| A | Первичный официальный | Госреестр, regulator, audited filing |
| B | Первичный корпоративный | Официальный сайт, отчёт компании |
| C | Профессиональный внешний | Качественное СМИ/исследователь |
| D | User submitted | Анкета компании до проверки |
| E | Непроверенный вторичный | Агрегатор/пост/форум |
Trust tier не означает автоматически «правда/ложь». Это input для verification workflow.
19. Confidence score
Не показывать пользователю псевдонаучную цифру «достоверность 87%» без смысла. Confidence нужен как внутренний triage signal.
confidence components:
source tier
identifier match
domain ownership
multiple-source agreement
recency
human verification
conflict signals
OUTPUT:
LOW / MEDIUM / HIGH
или internal numeric score
PUBLIC:
"подтверждено"
"сообщает компания"
"по данным источника X"
"не подтверждено"
20. Organization table
organizations
entity_id
organization_kind:
COMPANY
GROUP
NONPROFIT
GOVERNMENT
MEDIA
OTHER
display_name
description_short
founded_date_claim_id
status
primary_brand_id
primary_legal_entity_id
primary_domain_identifier_id
logo_asset_id
verification_level
profile_completeness
index_state
21. Legal entities
legal_entities
entity_id
jurisdiction
legal_form
registration_status
registration_date
dissolution_date
registered_address_id
IDs:
INN
OGRN
LEI
register number
etc.
relations:
part_of organization
operates brand
successor / predecessor
22. Person / Expert
persons
entity_id
display_name
first_name
last_name
bio_short
primary_photo_asset_id
verification_level
public_profile_state
relations:
EMPLOYED_BY
FOUNDER_OF
AUTHOR
INTERVIEWEE
EXPERT_IN_TOPIC
Sensitive personal data не должно собираться «на всякий случай». Public expert graph хранит только данные, необходимые продукту и имеющие законное основание.
23. Role не является колонкой Person
Должность — временная связь человека с организацией.
person_123
EMPLOYED_BY organization_9
qualifier:
role = "CMO"
valid_from = 2024-01
valid_to = 2026-06
person_123
EMPLOYED_BY organization_17
role = "CEO"
valid_from = 2026-07
24. Topics
topics
entity_id
preferred_name
definition
scope_note
topic_state
parent_topic_id optional
editorial_owner
index_state
aliases:
GEO
Generative Engine Optimization
AI Search Optimization
relations:
BROADER_THAN
NARROWER_THAN
RELATED_TO
Topic aliases участвуют в search/entity resolution, но не создают отдельные public pages.
25. Industry taxonomy
Не изобретать закрытую отраслевую классификацию навсегда. Хранить внутреннюю taxonomy и mappings к внешним классификаторам там, где это полезно.
industry entity:
"Software"
external mappings:
OKVED: ...
NAICS: ...
other taxonomy: ...
organization:
BELONGS_TO_INDUSTRY
qualifier:
primary=true
confidence=verified/derived
26. Product и Service
Schema.org различает Product, Service и Brand. «Матчасти» стоит хранить продукты уже на раннем этапе, потому что AI Visibility часто относится не только к компании, но и к конкретному продукту/категории.
| Поле | Product | Service |
| name | Да | Да |
| brand | Да | Может быть |
| offered_by | Organization | Organization |
| category/topics | Да | Да |
| public page MVP | Нет массово | Нет массово |
27. Publication как entity
publications
entity_id
publication_type:
ARTICLE
CASE
RESEARCH
NEWS
INTERVIEW
title
slug
publication_state
legal_status
editorial_status
authoring_model
published_at
updated_at
canonical_url
version_current_id
relations:
AUTHOR
ABOUT
CLIENT_IN_CASE
VENDOR_IN_CASE
SPONSOR_OF
TOPIC
SOURCE
28. Publication content и entity graph разделены
Rich text/blocks статьи не должны быть единственным местом, где записано, о каких компаниях она говорит.
CONTENT:
"В проекте компания Acme внедрила..."
STRUCTURED RELATION:
publication_44
VENDOR_IN_CASE → organization_acme
Это позволяет:
company profile
related content
reports
AI visibility
structured data
analytics
recommendations
29. Mention graph
Помимо сильных семантических отношений нужен более лёгкий слой mentions.
entity_mentions
publication_id
entity_id
mention_type:
BODY
TITLE
AUTHOR
SOURCE
QUOTE
CASE_ROLE
first_position
count
sentiment later
extraction_method:
MANUAL
AI
confidence
approved_by
AI может извлекать candidates, но публично значимые entity relations подтверждаются редактором или строгим rule engine.
30. AI не создаёт verified entity relation автоматически
LLM extraction = proposal, а не истина.
AI:
"похоже, Иван Иванов работает в Acme"
→ relation_candidate
THEN:
domain / source / editor verification
→ VERIFIED relation
или
→ REJECTED candidate
31. Entity resolution
Одна из главных будущих ценностей «Матчасти» — не создать 15 карточек одной компании.
NEW INPUT:
"ООО МАТЧАСТЬ"
domain: mathchast.com
INN: X
CANDIDATES:
entity 1 "Матчасть"
entity 2 "Mathchast"
signals:
identifier exact
domain exact
normalized name
address
brand relation
embedding similarity
decision:
MATCH
NEW_ENTITY
MANUAL_REVIEW
32. Entity resolution scoring
| Signal | Вес |
| Exact official identifier | Очень высокий |
| Verified domain match | Высокий |
| Exact legal name + jurisdiction | Высокий |
| Name similarity | Средний |
| Embedding similarity | Candidate generation only |
| Same logo | Поддерживающий signal |
| Только одинаковое короткое название | Недостаточно |
33. Merge
entity_merge
source_entity_id
target_entity_id
reason
approved_by
created_at
AFTER:
source status = MERGED
public source URL → 301 target
identifiers moved/deduplicated
relations moved
claims reconciled
aliases preserved
audit trail preserved
34. Split
Нужно уметь не только merge, но и split. Ошибочное объединение двух одноимённых компаний — реальный риск.
Поэтому merge не должен физически уничтожать историю. Должен быть reversible admin operation с audit trail.
35. Verification уровни
VERIFICATION
V0 UNVERIFIED
данные imported/submitted
V1 IDENTITY_CHECKED
идентификаторы/official domain подтверждены
V2 CONTROL_VERIFIED
представитель подтвердил управление company profile
V3 FACTS_VERIFIED
ключевые публичные claims проверены редакцией/источниками
НЕ:
"V3 = компания хорошая"
verification подтверждает идентичность/факты,
не качество бизнеса.
Детально — Mathchast_20.
36. Profile completeness ≠ verification
Completeness
Сколько полезных полей и связей заполнено.
Verification
Насколько подтверждены идентичность и конкретные утверждения.
Полная анкета может быть полностью непроверенной. Короткая карточка с реестровым ID может быть highly verified.
37. Index eligibility score
index eligibility inputs:
verified identifier
official domain
meaningful description
industry/topic
publications
experts
source coverage
duplicate status
legal status
thin-content risk
OUTPUT:
INTERNAL
NOINDEX
ELIGIBLE
INDEXABLE
Это отдельный score от verification и commercial status.
38. Public claims presentation
| Provenance | UI wording |
| Verified official registry | «По данным реестра...» / structured fact |
| Company-provided, checked | «Компания сообщает...» + source/date |
| Independent source | «По данным исследования X...» |
| Unverified company claim | Не показывать как neutral fact |
| Conflicting sources | Показать конфликт/дату или отправить на review |
39. Temporal snapshots
Для AI/Search reports особенно важно знать, как entity выглядела в конкретный момент.
company snapshot 2026-09-01:
name
domain
description
products
experts
claims
publication 2026-09-10
AI snapshot 2026-10-10
→ можно сравнивать before/after
не переписывая прошлое текущими данными.
40. Audit events
audit_events
actor_type:
USER / EDITOR / SYSTEM / AI
actor_id
action
object_type
object_id
before_json
after_json
reason
timestamp
request_id
Для критических изменений не полагаться только на application logs.
41. Source snapshots
Внешний URL может измениться. Для важных claims нужно хранить хотя бы metadata/content hash и, где это юридически/технически допустимо, внутренний snapshot используемого фрагмента/документа.
Нельзя бездумно архивировать чужие полные copyrighted pages. Snapshot policy должна учитывать права и тип источника.
42. Publication versioning
Документ 16 уже требует immutable published versions. В data model:
publication_versions
id
publication_id
version_number
content_json
title
summary
disclosure_snapshot
link_snapshot
entity_relations_snapshot
created_by
reason
published_at
content_hash
43. Address
addresses
id
country
region
city
street
postal_code
raw_text
normalized_text
lat/long optional
source_id
relations:
LEGAL_ENTITY REGISTERED_AT
ORGANIZATION OPERATES_AT
Не хранить один «адрес» без понимания его роли: юридический, офис, филиал, исторический.
44. Domain ownership
domain_identifiers
domain
entity_id
relation:
OFFICIAL
BRAND
PRODUCT
PREVIOUS
REDIRECT
UNKNOWN
verification_method:
DNS
EMAIL
FILE
MANUAL
OFFICIAL_SOURCE
verified_at
expires/recheck_at
45. Почему domain — сильный, но не вечный ID
Домены продаются, истекают и меняют владельцев. Поэтому domain нельзя использовать как immutable entity key. Он является identifier relation с временем и проверкой.
46. External same-entity mappings
| Mapping | Зачем |
| Wikidata | Disambiguation / external knowledge link |
| Official registry | Legal identity |
| LEI | International legal identity |
| Official website | Online presence |
| Authoritative social/company profile | Supporting identity |
Schema.org sameAs определяет URL как однозначную ссылку на тот же объект. Поэтому в будущем structured data нельзя заполнять sameAs любыми страницами, где компания просто упомянута.
47. Schema.org mapping
| Mathchast | Schema.org candidate |
| Organization | Organization / более специфичный subtype при необходимости |
| Legal entity | Обычно Organization + legalName / identifiers; внутреннее разделение богаче Schema.org |
| Brand | Brand |
| Person | Person |
| Product | Product |
| Service | Service |
| Publication | Article / NewsArticle etc. по типу |
Внутренняя модель не должна ограничиваться Schema.org. Structured data — экспортная проекция, а не primary database schema.
48. Важный нюанс ProfilePage
Google ProfilePage предназначен для страниц creator/person/organization, связанных с самим сайтом и публикующих first-hand perspectives. В документации Google в качестве некорректного примера прямо приведён organization review site, где организация не affiliated with website.
Следствие для будущего Mathchast_21:
- автор/эксперт, реально публикующийся на «Матчасти», может подходить под creator profile model;
- обычная карточка внешней компании в business directory не должна автоматически размечаться как Google
ProfilePage только потому, что это «профиль» в интерфейсе;
- для company page безопаснее проектировать WebPage + mainEntity Organization и затем проверить актуальные Google requirements.
49. Ownership/management permissions отдельно от entity
Компания существует независимо от того, есть ли у неё пользователь «Матчасти».
entities
≠
accounts
account_entity_permissions
account_id
entity_id
role:
OWNER
ADMIN
EDITOR
ANALYST
AGENCY_MANAGER
VIEWER
verification_id
valid_from
valid_to
Это фундамент для agency workspace и передачи управления профилем.
50. Agency не владеет entity клиента
AGENCY ACCOUNT
→ permission to manage Client A
→ permission to manage Client B
но:
Client A entity ownership/history independent
Client B entity ownership/history independent
если агентство уходит:
permissions revoked
entities/publications remain
51. Commercial relationships
Коммерческая связь тоже является данными, но не должна смешиваться с business ownership.
commercial_relationships
payer_account_id
beneficiary_entity_id
advertiser_entity_id
agency_entity_id optional
order_id
campaign_id
valid_from
valid_to
Это нужно для:
legal disclosure
billing
analytics
link policy
conflict of interest
52. Не хранить advertising status только в тексте статьи
legal_status, advertiser relation и sponsor relation должны быть структурированными полями, чтобы:
- рендерить маркировку;
- строить ОРД workflow;
- применять Link Policy;
- фильтровать partner content;
- аудировать конфликт интересов.
53. Search / semantic retrieval
PostgreSQL full-text/search index нужен для точных names/identifiers. pgvector — дополнительный слой для semantic discovery.
ENTITY SEARCH ORDER:
1. exact identifiers
2. exact normalized names
3. aliases
4. lexical/fuzzy search
5. domain match
6. vector candidates
7. manual disambiguation if needed
Векторное сходство не должно автоматически сливать entities.
54. Embeddings
entity_embeddings
entity_id
embedding_type:
DESCRIPTION
TOPIC_PROFILE
PUBLICATION_CORPUS
model
model_version
vector
generated_at
Хранить model/version, потому что embeddings разных моделей нельзя считать стабильным вечным идентификатором.
55. AI Visibility data не смешивать с core facts
CORE:
Company X exists
domain X
expert Y
publication Z
OBSERVATION:
On 2026-10-02
model M
prompt P
mentioned Company X
cited URL Z
position = 2
→ separate observations table
AI observation — событие измерения, не свойство компании.
56. Future AI observation schema
ai_observations
run_id
observed_at
provider
model
model_version
prompt_id
region/language
entity_id
mention_type
position
sentiment later
citation_url
citation_publication_id
raw_response_reference
parser_version
Детально — Mathchast_33.
57. Search observations
Тот же принцип:
search_observations
publication_id / entity_id
date
source:
GSC / Yandex / internal
impressions
clicks
query
position if source provides
country/device
source_account
Не записывать «позиция Google = 4» прямо в publication record.
58. Data ownership
| Данные | Source of truth |
| Legal identifiers | Registry / verified authoritative source |
| Company marketing description | Company submission + editorial state |
| Editorial description | Mathchast editorial |
| Commercial order | Billing/order system |
| Publication content | Publishing database/version store |
| AI observation | Measurement pipeline |
| Verification state | Verification subsystem |
59. Не перетирать editorial description маркетинговым текстом клиента
На company page нужны разные поля:
company_description_submitted
"как компания описывает себя"
editorial_summary
"нейтральное описание Матчасти"
legal_name
"что записано в реестре"
Все три могут отличаться,
и это нормально.
60. Data retention и deletion
Удаление account/person data, снятие публикации и удаление business entity — разные операции. Data model должна поддерживать:
SOFT DELETE
visibility off
history remains where lawful
HARD DELETE
only where required/appropriate
ANONYMIZE
person/account-specific fields
MERGE
entity remains as historical redirect/alias
TAKEDOWN
publication visibility/lifecycle state
Политика privacy будет детализирована позже; схема должна позволять исполнить её без разрушения всего graph.
61. Physical PostgreSQL modules
SCHEMA identity
entities
entity_names
entity_identifiers
organizations
legal_entities
persons
brands
products
services
addresses
SCHEMA graph
relations
relation_qualifiers
claims
claim_sources
entity_mentions
topics
industries
SCHEMA content
publications
publication_versions
publication_relations
assets
citations
SCHEMA trust
verifications
verification_evidence
merge_events
audit_events
SCHEMA commerce
orders
advertisers
campaigns
permissions
SCHEMA measurement
search_observations
ai_observations
publication_health
Физическое разделение schema можно упростить на MVP, но доменные границы полезно держать в архитектуре.
62. JSONB: где использовать
| Подходит | Не подходит |
| Редкие source-specific metadata | Ключевые identifiers |
| Raw import payload | Entity relations |
| AI parser raw metadata | Verification state |
| Publication block content | Допустимо при versioning |
| Extensible event metadata | Да |
Не складывать весь knowledge graph в один JSONB blob «потому что быстрее сделать».
63. IDs и foreign keys
Все core relations должны иметь реальные foreign keys. Human-readable slug и external identifier не заменяют внутренний ID.
64. Constraints
пример:
UNIQUE(scheme, jurisdiction, normalized_value)
WHERE verification_status='VERIFIED'
и identifier действительно уникален в этой scheme
CHECK valid_to >= valid_from
relation uniqueness:
subject + predicate + object + time window
с учётом history
publication canonical_url unique
current slug unique per route
Не вводить ложный global UNIQUE на company name или domain без временной модели.
65. Event model
Ключевые изменения генерируют domain events. Это свяжет entity graph с sitemap, IndexNow, analytics, recommendations и verification.
EntityVerified
CompanyUpdated
RelationVerified
PublicationPublished
PublicationUpdated
PublicationMoved
TopicPublished
EntityMerged
DomainChanged
listeners:
→ cache invalidate
→ sitemap update
→ IndexNow
→ structured data rebuild
→ embeddings refresh
→ analytics snapshot
66. Entity Graph API
internal API examples:
GET /entities/{id}
GET /entities/{id}/relations
GET /companies/{id}/publications
GET /experts/{id}/organizations
GET /topics/{id}/graph
POST /relations/candidates
POST /entities/merge
public API:
later, not MVP
67. Company Page query
company page assembles:
Organization core
+ preferred name
+ verified legal entities
+ official domain
+ editorial summary
+ topics/industries
+ experts with current temporal relations
+ publications by relation role
+ claims with allowed public provenance
+ verification badges
+ lifecycle/index state
68. Source traceability in UI
Не обязательно превращать страницу в Wikidata. Но важные факты должны иметь лёгкий путь к источнику:
Сотрудников: 120
[Источник: компания, обновлено 12.08.2026]
Основана: 2018
[Источник: официальный реестр]
Выручка: ...
[Источник / период]
69. Public provenance levels
| Уровень | UI |
| Basic | Источник и дата |
| Verified | Badge + source type |
| Conflicting | Notice / диапазон / несколько источников |
| Historical | Valid period |
70. Business advantage
Если «Матчасть» сделает эту модель правильно, через несколько лет её ценностью будет не коллекция статей, а история проверяемых связей бизнеса: кто с кем связан, кто что публиковал, какие продукты/эксперты фигурировали, какие источники это подтверждали и как менялась внешняя видимость.
71. Что не строить в MVP
| Не строить | Почему |
| Полноценный RDF triple store | Избыточно на старте |
| Neo4j cluster | Нет доказанной нагрузки/запросов, требующих его |
| 100 типов сущностей | Размывает MVP |
| Public product catalog | Thin/scaled-content риск |
| Автоматический merge по embedding | Высокий identity risk |
| Публичный confidence 0–100 | Псевдоточность |
| Полный импорт всех компаний РФ сразу | Не создаёт reader/product validation |
72. MVP data entities
P0:
Entity
Organization
LegalEntity
Brand
Person
Topic
Industry
Publication
Source
Identifier
Name/Alias
Relation
Claim
Verification
PublicationVersion
AuditEvent
P1:
Product
Service
Address normalization
EntityMention AI candidates
Embeddings
SearchObservation
P2:
AIObservation
Campaign
Reviews/Reputation
External media portfolio
73. Migration strategy
Нужно проектировать так, чтобы позже можно было добавить graph engine/warehouse, не переписывая meaning данных.
PostgreSQL = source of truth
later:
CDC / event stream
→ analytics warehouse
→ graph projection
→ vector indexes
→ public API
Не:
сначала 4 базы,
потом искать, где правда.
74. Решение документа
Утвердить provenance-aware temporal entity graph на PostgreSQL. Внутренний immutable entity ID отделяется от публичного URL и названия. Organization, Legal Entity, Brand и Person существуют отдельно. Связи имеют роли, источники и сроки действия. Изменяемые утверждения хранят provenance и verification state. Публичная страница является проекцией graph, а не source of truth. pgvector применяется для поиска кандидатов и рекомендаций, но не принимает identity decisions. Эта модель становится фундаментом structured data, moderation, verification, Search/AI Visibility и Next Best Publication.
75. Что этот документ разблокирует
Mathchast_19 entity graph
→ Mathchast_20 verification
→ Mathchast_21 structured data
→ Mathchast_22 crawlers / sitemap
→ Mathchast_23 content templates
→ Mathchast_24 CMS
→ Mathchast_25 AI precheck
→ Mathchast_26 distribution
→ Mathchast_33 AI visibility
→ Mathchast_35 next best publication
→ Mathchast_40 technical architecture
Источники исследования
- Google Search Central — Organization structured data: name, legalName, identifiers, logo, address, online presence и disambiguation
- Google Search Central — ProfilePage: mainEntity Person/Organization и ограничения use case
- Schema.org — Brand
- Schema.org — brand relation для Organization/Person/Product/Service
- Wikidata — Data model: entity statements subject/predicate/object, qualifiers и временные свойства
- W3C PROV Model Primer — provenance, entities, activities, agents, responsibility, roles and time
- W3C PROV Overview — provenance как основа оценки качества, надёжности и доверия к данным
- OpenCorporates Data Dictionary — company_number + jurisdiction_code как идентификационная основа и отдельное хранение legal name/company type
Конкретная SQL-схема, relation vocabulary, verification levels, index eligibility, trust tiers и module boundaries являются проектными решениями «Матчасти». Schema.org и Google markup не используются как primary database schema: они рассматриваются как будущие внешние представления внутренней более богатой модели.