Pular para o conteúdo

Pesquisando objetos de negócio e nós

A API do RealityConnect expõe duas rotas de pesquisa com escopos diferentes: a pesquisa de objetos de negócio procura dentro de um twin por POIs, zonas, ativos e seus metadados, enquanto a pesquisa de nós procura na hierarquia de nós da sua organização (sites, pastas, twins e arquivos). Ambas as rotas são experimentais e podem mudar.


MétodoCaminhoEscopoFinalidade
GET/v1/twin/{contextId}/searchBasicPesquisar objetos de negócio e metadados dentro de um twin
GET/v1/nodes/searchReadHierarchyPesquisar na hierarquia de nós da organização

GET /v1/twin/{contextId}/search pesquisa POIs, zonas, box assets, medições e outros objetos de negócio dentro de um único twin (ou um de seus sites/rascunhos, identificado por contextId), comparando nome, campos reservados, metadados de ativo e propriedades específicas do objeto.

ParâmetroTipoNotas
fieldFiltersarray de objetos JSONFiltros de chaves reservadas. Veja abaixo.
metadataFiltersarray de objetos JSONCompara propriedades de metadados de ativo do twin. Veja abaixo.
additionalPropertyFiltersarray de objetos JSONCompara propriedades específicas do tipo de objeto (ex.: o icon de um POI). Veja abaixo.
pageinteiroPositivo, padrão 1.
limitinteiro150, padrão 50.
searchNameQuerystringFiltro de nome dedicado, independente do nome em fieldFilters.
nameMatchexact | containsModo de correspondência para searchNameQuery. Padrão contains.
createdByIduuidFiltrar por criador.
createdBefore / createdAftertimestampEstritamente antes/depois. Formato YYYY-MM-DDTHH:mm:ss (sem fuso horário, sem milissegundos).
updatedBefore / updatedAftertimestampMesmo formato.
sortByname | createdAt | updatedAtCampo de ordenação.
sortDirASC | DESCDireção de ordenação.

fieldFilters, metadataFilters e additionalPropertyFilters são enviados cada um como uma string de objeto JSON por filtro, repetindo o parâmetro de consulta para vários filtros:

?fieldFilters={"key":"type","values":["poi"]}&fieldFilters={"key":"type","values":["zone"]}

Cada objeto de filtro tem a forma { "key": string, "values": string[] }. Vários valores no array values de um mesmo filtro são combinados com OR.

fieldFilters aceita apenas estas chaves reservadas — qualquer outra chave é silenciosamente ignorada:

ChaveCompara
typeTipo de objeto de negócio. Aceita o valor do enum (Poi, Zone, BoxAsset, CubePrimitive, PlanePrimitive, DistanceMeasure, CoordinateMeasure, DiameterMeasure, SurfaceMeasure, OrthogonalMeasure, Cut, ModelAsset) ou seu token normalizado em kebab-case — uma versão com hifens e em minúsculas do nome PascalCase, ex.: BoxAssetbox-asset.
asset-typeO tipo de ativo do objeto (mapeado para assetTypeId). Correspondência exata.
nameCorrespondência por prefixo apenas no nome, sem difusão.
idCorrespondência exata do id do objeto.

Os valores de fieldFilters são sempre strings simples ou tokens de enum — a sintaxe numérica/de intervalo abaixo não se aplica a eles.

metadataFilters e additionalPropertyFilters referenciam por chave uma propriedade de metadados definida no schema (metadataFilters) ou uma propriedade específica do tipo de objeto que não faz parte dos metadados comuns (additionalPropertyFilters, ex.: o icon de um POI). Cada valor em values suporta:

Sintaxe do valorSignificado
String simplesCorrespondência exata. Várias strings simples em values são combinadas com OR.
* ou string vaziaIgnorado — se for o único valor, o filtro corresponde apenas pela presença da chave.
=123, !=123, >123, >=123, <123, <=123Comparação numérica. Inteiros, decimais e notação científica (ex.: 1.5e+35) são suportados.
range:[1..10]Intervalo numérico inclusivo.
range:(1..10)Intervalo numérico exclusivo.
range:[1..10) / range:(1..10]Limites mistos inclusivo/exclusivo.
true / falseApenas em additionalPropertyFilters — compara literalmente uma propriedade booleana.

fieldFilters, metadataFilters e additionalPropertyFilters combinam-se com semântica AND: um resultado precisa satisfazer cada filtro. Dentro de um único filtro, os valores no seu array values são combinados com OR — assim, dois objetos fieldFilters que compartilham a mesma key funcionam como “qualquer um dos valores corresponde”, enquanto filtros em chaves diferentes (ou em arrays de filtro diferentes) restringem ainda mais o conjunto de resultados.

Filtro de tipo combinado com um intervalo numérico de metadados (POIs com uma pressão de inspeção registrada entre 80 e 120):

GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22type%22%2C%22values%22%3A%5B%22poi%22%5D%7D&metadataFilters=%7B%22key%22%3A%22inspection.pressure%22%2C%22values%22%3A%5B%22range%3A%5B80..120%5D%22%5D%7D
Authorization: Bearer {access_token}

Tipo de ativo combinado com um filtro de nome, atualizações mais recentes primeiro:

GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22asset-type%22%2C%22values%22%3A%5B%22pump%22%5D%7D&fieldFilters=%7B%22key%22%3A%22name%22%2C%22values%22%3A%5B%22vibration%22%5D%7D&sortBy=updatedAt&sortDir=DESC
Authorization: Bearer {access_token}

Isso significa: objetos cujo tipo de ativo é pump e cujo nome começa com “vibration”, ordenados pelos mais recentemente atualizados.

Dois fieldFilters na mesma chave (combinados com OR) combinados com um fieldFilters em uma chave diferente (combinado com AND) — POIs ou zonas, restritos ao tipo de ativo pump:

GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22type%22%2C%22values%22%3A%5B%22poi%22%2C%22zone%22%5D%7D&fieldFilters=%7B%22key%22%3A%22asset-type%22%2C%22values%22%3A%5B%22pump%22%5D%7D
Authorization: Bearer {access_token}

Um literal booleano de additionalPropertyFilters combinado com uma correspondência de string em metadataFilters — POIs ativos cujos metadados adjacentes ao ícone registram um status “warning”:

GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22type%22%2C%22values%22%3A%5B%22poi%22%5D%7D&additionalPropertyFilters=%7B%22key%22%3A%22isActive%22%2C%22values%22%3A%5B%22true%22%5D%7D&metadataFilters=%7B%22key%22%3A%22inspection.status%22%2C%22values%22%3A%5B%22warning%22%5D%7D
Authorization: Bearer {access_token}

Uma requisição completa combinando todas as três entradas de filtro, um filtro de nome dedicado, um intervalo de datas, paginação e ordenação — mostrando a forma completa da requisição:

GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22type%22%2C%22values%22%3A%5B%22poi%22%2C%22zone%22%5D%7D&metadataFilters=%7B%22key%22%3A%22inspection.pressure%22%2C%22values%22%3A%5B%22range%3A%5B80..120%5D%22%5D%7D&additionalPropertyFilters=%7B%22key%22%3A%22isActive%22%2C%22values%22%3A%5B%22true%22%5D%7D&searchNameQuery=Pump&nameMatch=contains&updatedAfter=2026-01-01T00%3A00%3A00&updatedBefore=2026-12-31T23%3A59%3A59&page=1&limit=25&sortBy=updatedAt&sortDir=DESC
Authorization: Bearer {access_token}
sortByOrdena por
nameNome do objeto
createdAtTimestamp de criação
updatedAtTimestamp da última atualização

Cada valor de sortBy combina com qualquer valor de sortDir:

GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22type%22%2C%22values%22%3A%5B%22poi%22%5D%7D&sortBy=name&sortDir=ASC
Authorization: Bearer {access_token}
GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22type%22%2C%22values%22%3A%5B%22poi%22%5D%7D&sortBy=createdAt&sortDir=DESC
Authorization: Bearer {access_token}
GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22type%22%2C%22values%22%3A%5B%22poi%22%5D%7D&sortBy=updatedAt&sortDir=DESC
Authorization: Bearer {access_token}

sortDir tem como padrão ASC quando omitido. sortBy não tem um campo padrão documentado — omiti-lo faz a ordenação usar uma pontuação de relevância interna (decrescente), com id (crescente) como critério de desempate. Apenas fieldFilters com key: "name" afeta essa pontuação; qualquer outro filtro é uma correspondência binária (sim/não) sem efeito no ranqueamento, então, na prática, omitir sortBy sem um filtro de name retorna os resultados na ordem de id. Isso é um detalhe de implementação, não um contrato garantido — defina sortBy explicitamente sempre que uma ordem de campo específica for importante para a sua integração.

Dentro dos valores de metadataFilters e additionalPropertyFilters, um valor pode carregar um operador de comparação ou um intervalo em vez de corresponder literalmente. Essa sintaxe não se aplica a fieldFilters — esses são sempre correspondência literal/enum (type, asset-type, name, id).

OperadorExemploSignificado
==123Igual a
!=!=123Diferente de
>>123Maior que
>=>=123Maior ou igual a
<<123Menor que
<=<=123Menor ou igual a
range:[a..b]range:[80..120]Inclusivo em ambos os limites
range:(a..b)range:(80..120)Exclusivo em ambos os limites
range:[a..b)range:[80..120)Inclusivo no limite inferior, exclusivo no superior
range:(a..b]range:(80..120]Exclusivo no limite inferior, inclusivo no superior

Inteiros, decimais, números negativos e notação científica são todos suportados, ex.: >=-40, =3.14, ou range:[1.5e+35..2.0e+35].

Existem duas formas de comparar por nome, e elas se comportam de maneira diferente:

ParâmetroEstilo de correspondênciaCombina com outros filtros?
fieldFilters={"key":"name",...}Correspondência por prefixo, sem difusãoSim — sempre combina com AND
searchNameQuery + nameMatchcontains (padrão) ou exact, sem difusãoSim — sempre combina com AND

Use fieldFilters com key: "name" para uma correspondência por prefixo apenas de nome, que se combina sob as mesmas regras AND/OR que type ou asset-type. Use searchNameQuery com nameMatch quando precisar de uma busca precisa por substring ou por nome exato sem tolerância a difusão — por exemplo, para validar que um nome existe literalmente.

{
"results": [
{
"id": "5e1c0b3a-2d9a-4b7d-8f0b-9a2c8f1b7a10",
"name": "Fire extinguisher 12",
"type": "Poi",
"matchedFields": [
{ "matchKey": "name", "highlight": "Fire <em>extinguisher</em> 12" }
],
"createdAt": "2026-06-01T10:00:00.000Z",
"updatedAt": "2026-06-01T10:00:00.000Z",
"createdById": "8f0b9a2c-8f1b-4a10-9e1c-0b3a2d9a4b7d"
}
],
"count": 1
}

matchedFields mostra qual campo ou propriedade de metadados correspondeu, com o texto correspondido envolvido em <em>. matchKey é um nome de campo raiz (ex.: name) ou @<metadata-path> para um valor de metadados ou propriedade aninhada que correspondeu.

Um único resultado pode carregar várias entradas em matchedFields — uma para cada campo ou propriedade de metadados que correspondeu. Por exemplo, uma requisição combinada de correspondência de nome via fieldFilters e metadataFilters que corresponde tanto ao nome do objeto quanto a um valor de metadados de inspeção retorna:

{
"id": "5e1c0b3a-2d9a-4b7d-8f0b-9a2c8f1b7a10",
"name": "Pressure gauge 04",
"type": "Poi",
"matchedFields": [
{ "matchKey": "name", "highlight": "<em>Pressure</em> gauge 04" },
{ "matchKey": "@inspection.status", "highlight": "<em>Warning</em>: recalibration due" }
],
"createdAt": "2026-06-01T10:00:00.000Z",
"updatedAt": "2026-06-01T10:00:00.000Z",
"createdById": "8f0b9a2c-8f1b-4a10-9e1c-0b3a2d9a4b7d"
}

Os fragmentos de destaque têm o HTML escapado antes que os marcadores <em> sejam inseridos, então qualquer <, > ou & no texto correspondido chega como &lt;, &gt; ou &amp; em vez de markup bruto — seguro para renderizar diretamente em HTML sem uma segunda passagem de escape, mas decodifique-o primeiro se precisar do valor em texto simples.

SituaçãoComportamento
Nenhum filtro (ou todos vazios)Retorna todos os objetos de negócio do twin, até o limit, sem ranqueamento (match_all).
Uma chave de fieldFilters não reconhecidaSilenciosamente ignorada — o filtro não contribui em nada para a consulta, não gera um 400.
Um valor de metadataFilters/additionalPropertyFilters igual a * ou ""Ignorado. Se todos os valores no array values desse filtro forem ignorados dessa forma, o filtro ainda exige que o objeto tenha uma propriedade nessa chave — tornando-se uma verificação de presença de chave sem restrição de valor.

Busca por prefixo de nome:

GET {api_url}/v1/twin/{contextId}/search?fieldFilters=%7B%22key%22%3A%22name%22%2C%22values%22%3A%5B%22extinguisher%22%5D%7D
Authorization: Bearer {access_token}

Busca por conteúdo de nome ordenada por nome:

GET {api_url}/v1/twin/{contextId}/search?searchNameQuery=Pump&nameMatch=contains&sortBy=name&sortDir=ASC
Authorization: Bearer {access_token}
StatusCausa
400 Bad RequestUm valor de fieldFilters, metadataFilters ou additionalPropertyFilters não é um JSON válido, ou não corresponde à forma { key, values }.

Parâmetros de filtro repetidos (vários fieldFilters, metadataFilters ou additionalPropertyFilters com valores JSON diferentes) não podem ser construídos com o params baseado em dicionário do requests — um dicionário só admite um valor por chave. Construa você mesmo a query string com urllib.parse.urlencode e uma lista de tuplas:

import json
import requests
from urllib.parse import urlencode
API_URL = "https://<your-regional-api-url>"
TOKEN = "<access_token>"
CONTEXT_ID = "<twin-id>"
headers = {"Authorization": f"Bearer {TOKEN}"}
params = [
("fieldFilters", json.dumps({"key": "type", "values": ["poi"]})),
("metadataFilters", json.dumps({"key": "inspection.pressure", "values": ["range:[80..120]"]})),
("sortBy", "name"),
("sortDir", "ASC"),
]
response = requests.get(
f"{API_URL}/v1/twin/{CONTEXT_ID}/search?{urlencode(params)}",
headers=headers,
).json()
for result in response["results"]:
print(result["type"], result["name"], result["id"])

GET /v1/nodes/search pesquisa na hierarquia de nós da sua organização — divisões, sites, pastas, twins, bibliotecas de ativos e arquivos de dados — em vez dos objetos de negócio dentro de um twin. A organização é resolvida a partir do token de acesso, não passada como parâmetro.

ParâmetroTipoNotas
nodeTypesarray de DataNodeTypeFiltra para um ou mais tipos de nó. Repita o parâmetro, ex.: ?nodeTypes=Site&nodeTypes=Folder. Valores: Organization, Site, Pointcloud, Mesh, SiteFile, Folder, Project, Division, Artifact, DataBundle, Twin, AssetLibrary.
excludeNodeTypesarray de DataNodeTypeExclui um ou mais tipos de nó. Mesma sintaxe de repetição.
searchNameQuerystringFiltra por nome do nó.
nameMatchexact | containsModo de correspondência para searchNameQuery. Padrão contains.
parentIduuidApenas filhos diretos deste nó.
ancestorIduuidDescendentes em qualquer profundidade, excluindo o próprio ancestral. Use para conteúdo aninhado sob um site ou pasta; use parentId apenas para filhos diretos.
createdByIduuidFiltrar por criador.
createdBefore / createdAftertimestampEstritamente antes/depois. Formato YYYY-MM-DDTHH:mm:ss.
updatedBefore / updatedAftertimestampMesmo formato.
bytesStoredinteiroCorrespondência exata.
minBytesStored / maxBytesStoredinteiroLimites inclusivos.
childrenCountinteiroCorrespondência exata.
minChildrenCount / maxChildrenCountinteiroLimites inclusivos.
includesThumbnail'true' | 'false'Inclui URLs de miniatura assinadas quando disponíveis. Padrão 'false'.
pageinteiroPadrão 1.
limitinteiro150, padrão 20.
sortByname | createdAt | updatedAt | bytesStored | childrenCountCampo de ordenação.
sortDirASC | DESCDireção de ordenação. Padrão ASC.
{
"items": [
{
"id": "a6f75b3c-f261-4b27-9a2a-9a6cc1234c53",
"createdAt": "2026-06-01T10:00:00.000Z",
"updatedAt": "2026-06-01T10:00:00.000Z",
"name": "Building A",
"type": "Site",
"createdById": "8f0b9a2c-8f1b-4a10-9e1c-0b3a2d9a4b7d",
"parentId": "d2a1c4b7-3e10-4f2c-9a6b-7c1d8e2f3a45",
"childrenCount": 4,
"bytesStored": 15728640,
"thumbnailSignedUrl": null
}
],
"total": 1
}

Todos os sites sob um nó ancestral:

GET {api_url}/v1/nodes/search?nodeTypes=Site&ancestorId=d2a1c4b7-3e10-4f2c-9a6b-7c1d8e2f3a45
Authorization: Bearer {access_token}

Pastas cujo nome começa com “Archive”, ordenadas por nome:

GET {api_url}/v1/nodes/search?nodeTypes=Folder&searchNameQuery=Archive&nameMatch=contains&sortBy=name&sortDir=ASC
Authorization: Bearer {access_token}
import requests
from urllib.parse import urlencode
API_URL = "https://<your-regional-api-url>"
TOKEN = "<access_token>"
ANCESTOR_ID = "<division-or-site-id>"
headers = {"Authorization": f"Bearer {TOKEN}"}
params = [
("nodeTypes", "Site"),
("ancestorId", ANCESTOR_ID),
("sortBy", "name"),
("sortDir", "ASC"),
]
response = requests.get(
f"{API_URL}/v1/nodes/search?{urlencode(params)}",
headers=headers,
).json()
for node in response["items"]:
print(node["type"], node["name"], node["id"])

Para criar recursos sob um nó retornado pela pesquisa de nós, consulte Criando um data bundle.