nextgis / nextgisweb

Web GIS framework by NextGIS
https://nextgis.com/nextgis-web/
GNU General Public License v3.0
216 stars 95 forks source link

Путаница с fid #301

Closed alisovenko closed 4 years ago

alisovenko commented 9 years ago

В ngw: слой - RU-KLU-OBNINSK (http://demo.nextgis.ru/ngw/resource/1316) карта - RU-KLU-MAP (http://demo.nextgis.ru/ngw/resource/1309) объект c fid=4 (большой полигон в центре) имеет фото 3 шт. (например, http://demo.nextgis.ru/ngw/layer/1316/feature/4/photo/4)

Загружаю слой в ngq как geojson - все ОК. Тот же объект (большой полигон в центре) имеет fid 4.

Проблема: Загружаю слой в ngq через WFS (http://demo.nextgis.ru/ngw/resource/1311) - fid не соответствует. Тот же объект (большой полигон в центре) имеет fid 3.

KolesovDmitry commented 9 years ago

@alisovenko несколько вопросов:

alisovenko commented 9 years ago
  1. Да, OSM_ID = 89383129
  2. В QGIS добавляю WFS: http://demo.nextgis.ru/ngw/resource/1311/wfs, там слой RU-KLU-OBNINSK. Использую инструмент "Определить объекты", в окне "Результат определения" параметр "ID объекта" = 3 (этот полигон OSM_ID = 89383129)

Если грузить GeoJSON и идентифицировать этот объект - то параметр "ID объекта" = 4.

Или "ID объекта" это может не fid... Но в общем с "ID объекта" = 4 в NGW я могу получить данные об объекте (этот полигон OSM_ID = 89383129), а с "ID объекта" = 3 - это уже другой объект в NGW

BishopGIS commented 9 years ago

У нас на id в мобильном строится вся синхронизация. Очень важно, что бы циферки не отличались. Сейчас что в GeoJSON, что в api/resource//feature/ id бьют.

KolesovDmitry commented 9 years ago

Тут очень темное дело, я не могу понять, что происходит. Дело в том, что WFS-сервер оперирует теми самыми идентификаторами, которые нужны, вот примеры:

  1. Когда QGIS запрашивает объекты, то они приходят со своими идентификаторами, например: http://demo.nextgis.ru/ngw/resource/1311/wfs?SERVICE=WFS&REQUEST=getfeature&VERSION=1.0.0&TYPENAME=rukluobninsk4wfs там видно, что в ответе указывается идентификатор объекта с OSN_ID =89383129 равняется четырем (см. <gml:featureMember gml:id="4"> и ниже).
  2. Если бы была путаница в идентификаторах, то при редактировании атрибутов по WFS-T одного объекта, они изменялись бы у другого. Этого не происходит.
  3. Если протрассировать выполнение запросов в коде WFS-сервера, то видно, что там идентификаторы "правильные": когда добавляется/редактируется объект, то WFS-сервер согласно стандарту должен получить/отослать идентификатор созданного/измененного объекта. При трассировке fid нашего объекта равен именно четырем, а не трем.

При этом, если создать, к примеру, новый объект, то ему будет назначен fid=X. Во всех упоминаниях в обмене сообщениями между QGIS и WFS-серером этот объект будет нумероваться именно как X. Однако, если посмотреть его через инструмент "Определить объекты", то ID объекта не будет равен X.

Подводя итоги: при обмене сообщениями по протоколу WFS все объекты идентифицируются при помощи "настоящих" fid. Но при использовании инструмента "Определить объекты" отображается какой-то внутренний ID объекта (даже понятно какой -- qgis просто нумерует объекты, начиная с 0 и не учитывая fid, и этот номер и будет ID, отображаемый при определении).

Гипотеза: где-то между QGIS и WFS-сервером порвалась цепочка, по которой QGIS забирает идентификатор объекта. Эти идентификаторы не поступают в QGIS, и он выкручивается, как может.

Было бы неплохо, если бы кто-нибудь мог дать:

BishopGIS commented 9 years ago

А может там нумерация с 1, а везде с 0?

KolesovDmitry commented 9 years ago

@BishopGIS Нет, там дело не в том, что сбилась нумерация 0 и 1. После того, как я повставлял-понаудалял объекты, разность между идентификаторами уже больше одного. Например, если вставить новый объект, то у него идентификатор в БД (fid) будет равен 18 (предыдущие 17 уже были использованы, а поле идентификатора в БД -- serial). При этом ID в QGIS этого объекта будет равно 13 (поскольку всего 14 объектов, и они нумеруются в QGIS: ID=0, ID=1, ... ID=13).

KolesovDmitry commented 9 years ago

Я думаю, проблема на стороне QGIS. Правда, прямых доказательств не нашел, только косвенные:

  1. Не нашел отступлений от стандарта в XML-ках, учавствующих в обмене сообщениями между WFS-сервером и QGIS.
  2. Если взять WFS-сервер (например, http://map.rostmuseum.ru/scripts/tinyows/tinyows.cgi), который работает на другом движке, то ситуация повторяется -- идентификаторы, передаваемые сервером, не отображаются в инструменте идентификации.

Таким образом, я думаю, что QGIS попросту игнорирует эти идентификаторы, а нумерует их по-своему -- начинает с нуля и идет по порядку.

Для того, чтобы проверить предположение, смотрю в исходных кодах QGIS функции, которые отвечают за транзакции. Эти функции должны работать с идентификаторами, которые присутствуют в БД, иначе все операции редактирования пойдут наперекосяк.

Для примера https://github.com/qgis/QGIS/blob/master/src/providers/wfs/qgswfsprovider.cpp#L383 -- функция удаления объектов:

  1. Получает список/массив идентификаторов объектов, которые нужно удалить (https://github.com/qgis/QGIS/blob/master/src/providers/wfs/qgswfsprovider.cpp#L383).
  2. Производит поиск объектов и удаляет: https://github.com/qgis/QGIS/blob/master/src/providers/wfs/qgswfsprovider.cpp#L407-L422 При этом:
    1. Сами идентификаторы имеет тип QgsFeatureIds (https://github.com/qgis/QGIS/blob/master/src/providers/wfs/qgswfsprovider.cpp#L407-L422), который определяется тут http://qgis.org/api/qgsfeature_8h.html как typedef QSet< QgsFeatureId > QgsFeatureIds. Т.е. это те самые "внутренние" идентификаторы объектов, используемые в QGIS.
    2. Преобразование "внутренних" идентификаторов в fid, которые используются в БД, производится внутри помеченной выше процедуры на этих строках: https://github.com/qgis/QGIS/blob/master/src/providers/wfs/qgswfsprovider.cpp#L411 и https://github.com/qgis/QGIS/blob/master/src/providers/wfs/qgswfsprovider.cpp#L417.

Если я все правильно разобрал в этом коде, то это не баг NGW, а фишка QGIS. Тем не менее у меня остаются сомнения в том, что я верно интерпретировал эти строки, поскольку я не знаком с C++. @BishopGIS, не мог бы ты проверить ход рассуждений и прокомментировать его?

simgislab commented 9 years ago

@alexbruy тоже глянь плиз

yellow-sky commented 9 years ago

Дим, твои исследования верны. В слое хранится маппинг реальных ид (с сервера) с виртуальными кугисовскими: https://github.com/qgis/QGIS/blob/master/src/providers/wfs/qgswfsprovider.h#L187 Проблема в том, что снаружи к этому маппингу нет доступа :(

@alexbruy нам нужна твоя помощь. Можешь ли ты добавить метод возврата реального ид по виртуальному?

dezhin commented 4 years ago

Видимо это можно закрывать, похожее поведение мы наблюдаем и с новым WFS сервером в NGW. Видимо ноги мэппинга растут из того, что идентификаторы объекта в WFS - не число, а строка в общем случае. Но вроде бы это не приводит к проблемам.