Как я могу контролировать тип геометрии перед обновлением - PullRequest
0 голосов
/ 01 ноября 2019

У меня есть метод rails, который объединяет многоканальную строку в линейную строку.

Иногда я получаю сообщение об ошибке в данных и получаю следующее сообщение об ошибке:

Тип геометрии (MultiLineString) не соответствует столбцутип (LineString).

Как я могу контролировать его и предотвратить ошибки? Могу ли я сделать это прямо в запросе sql?

def update_path(trace)
  trace.update(path: merge_tracks(trace))
end

def merge_tracks(trace)
  tracks = <<-SQL
    SELECT ST_AsText(St_linemerge(ST_Collect(tr.path))) as geojson
      FROM tracks tr
      INNER JOIN trace_tracks ON tr.id = trace_tracks.track_id
      WHERE trace_tracks.trace_id = #{trace.id}
  SQL
  ActiveRecord::Base.connection.execute(tracks).getvalue(0,0)
end

1 Ответ

0 голосов
/ 02 ноября 2019

Было бы полезно, если бы вы могли включить пример LineStrings, которые возвращают MultiLineString. Но это, вероятно, потому что LineStrings не разделяют общую точку и поэтому не могут быть объединены.

Если вы в порядке, выбрасывая эти строки, а не исправляя их, это должно работать:

SELECT ST_AsGeoJson(St_linemerge(ST_Collect(tr.path))) as geojson
      FROM tracks tr
      INNER JOIN trace_tracks ON tr.id = trace_tracks.track_id
      WHERE trace_tracks.trace_id = #{trace.id}
      AND ST_GeometryType(St_linemerge(ST_Collect(tr.path))) = 'ST_Linestring';

Если вы хотите сохранить их и все в порядке, возвращая более одной строки, тогда вы можете сделать:

SELECT ST_AsGeoJson(geom) as geojson
   FROM
   (SELECT (ST_Dump(ST_LineMerge(ST_Collect(tr.path)))).*
      FROM tracks tr
      INNER JOIN trace_tracks ON tr.id = trace_tracks.track_id
      WHERE trace_tracks.trace_id = #{trace.id}
    ) g;

Если вы хотите принудительно создать линию из точек мультилинии (т.е. соединить две непересекающиеся линии вместе), возможно, с неожиданными результатами, вы можете сделать это (ИСПОЛЬЗОВАТЬ ATВАШ СОБСТВЕННЫЙ РИСК):


SELECT ST_AsGeoJson(ST_MakeLine(geom)) as geojson
   FROM
   (SELECT (ST_DumpPoints(tr.path)).*
      FROM tracks tr
      INNER JOIN trace_tracks ON tr.id = trace_tracks.track_id
      WHERE trace_tracks.trace_id = #{trace.id}
    ) g;

Это просто соединяет конец одной строки с началом следующей в любом порядке, в котором хранятся строки.

...