Сопоставить поля класса ассоциации в рекурсивной структуре - PullRequest
0 голосов
/ 04 февраля 2019

У меня есть следующая структура данных моих данных, хранящихся в коллекции MongoDB.

data model

Одна из записей данных выглядит следующим образом:

{
    "id": 0,
    ...
    "structure": {
        "id": 0,
        "name": "rsu2",
        "peers": [
            {
                "networkQuality": {
                    "name": "3G",
                    "latency": "200ms",
                    "bandwidth": "1000kbps"
                },
                "connectionEndpoint": {
                    "id": 1,
                    "name": "vehicle1",
                    "peers": []
                }
            },
            {
                "networkQuality": {
                    "name": "3G",
                    "latency": "200ms",
                    "bandwidth": "1000kbps"
                },
                "connectionEndpoint": {
                    "id": 2,
                    "name": "vehicle2",
                    "peers": []
                }
            }
        ]
    }
}

Мой вопрос таков: как я могу получить топологии, которые имеют networkQuality.name = '3G' для всех соединений между любыми двумя узлами.
Это моя идея, но так как я не такУ меня еще нет опыта работы с MongoDB, я не знаю точно, как сформулировать его в рабочий запрос.

  • Поскольку это рекурсивная структура, я бы использовал функцию javascript, определенную в операторе $ where ( как здесь ) для сопоставления networkQuality.name = '3G' в любом месте рекурсивной структуры.
  • В соответствии с подходом, описанным в предыдущем пункте, я бы получил все топологии, имеющие хотя бы одно имя networkQuality.name.= '3G' и топологии, имеющие хотя бы одну сетьQuality.name! = '3G'.После этого у меня есть два комплекта.Когда я применяю операцию set minus к ним (первый результат - второй результат), я получаю желаемый результат.

У кого-нибудь есть идеи, как это сделать?

1 Ответ

0 голосов
/ 06 февраля 2019

К сожалению, я не могу решить эту проблему, используя только один запрос, но я нашел два запроса и выполняю простую «обработку JavaScript» между ними.

Первое изменение заключается в том, что я не храню топологиюсо встроенными узлами в той же коллекции, но у меня есть одна коллекция для моих топологий и другая для узлов.
Структура коллекции топологии проста:

{
    "caption": "small-i=1-net=3G"
    "id": 0
    "specification": "tosca"
    "specificationLang": "tosca"
    "structure_root_node_id": 0
}

И я решил сохранить структуру узлов какдерево с дочерними ссылками.Точно так же, как в документации mongodb здесь .

Означает, что документ, представляющий узел, хранится так:

{ 
    "id": 0
    "connections" : [ 
        { 
            "networkQuality" : 
                { 
                    "name" : "3G", 
                    "latency" : "200ms", 
                    "bandwidth" : "1000kbps" 
                }, 
            "endpoint_id" : 1 
        }, 
        { 
            "networkQuality" : 
                { 
                    "name" : "3G", 
                    "latency" : "200ms", 
                    "bandwidth" : "1000kbps"
                }, 
            "endpoint_id" : 2 } 
        ],
    "name" : "edge1", 
    "nodeType" : 1
}

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

[{$lookup: {
  from: 'node_structure',
  localField: 'structure_root_node_id',
  foreignField: 'id',
  as: 'structure'
}}, {$graphLookup: {
  from: 'node_structure',
  startWith: '$structure.id',
  connectFromField: 'connections.endpoint_id',
  connectToField: 'id',
  as: 'endpoints'
}}, {$project: {
  "endpoints.id": 1
}}]

Запустив вышеуказанный конвейер, я получаю массив, содержащий все идентификаторы узлов моей топологии.

{ 
    "_id" : ObjectId("5c5af8c6dfe2bc05bfc6ed0b"), 
    "endpoints" : 
        [ 
            { "id" : 4 }, 
            { "id" : 1 }, 
            { "id" : 0 }, 
            { "id" : 2 }, 
            { "id" : 3 } 
        ] 
}

2.Это этап обработки JS, где мне нужно извлечь идентификаторы из массива конечных точек в следующую форму: [4, 1, 0, 2, 3] (было бы хорошо, если бы я мог сделать это как частьтрубопровод, но не знаю, если это возможно).

3.Выполнить поиск

{
    $and: [
        { connections: { $elemMatch: { 'networkQuality.name': { $nin: ['3G'] } } } },
        { id: { $in: [0, 1, 2, 3, 4] } }
    ]
}

Это вернет любой узел, имеющий хотя бы одно соединение, отличное от '3G', означает, что , если запрос ничего не возвращает, я нашел топологию со всеми соединениями между любымидва узла с сетевым качеством. name = '3G'.
Было бы неплохо решить все это одним запросом, но это единственное решение, которое я нашел к настоящему времени.(примечание: я не хочу хранить идентификаторы узлов всех топологий в поле топологии)

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