Giter VIP home page Giter VIP logo

appendfeaturestolayer's Introduction

Unit tests Release

Append Features to Layer

QGIS v3 plugin that adds a new Processing algorithm to append/update features from a source vector layer to an existing target vector layer.

License: This plugin is distributed under the GNU GPL v3 license.

โžก๏ธ Use cases
๐Ÿ› ๏ธ How does it work
๐Ÿ”Ž Where to find the algorithm
๐Ÿ“ Examples
๐Ÿ Using Append Features to Layer in standalone PyQGIS scripts
โš™๏ธ Using Append Features to Layer via QGIS Process
๐Ÿ’ป Running Unit Tests Locally


โžก๏ธ Use cases

  1. Copy & Paste features:

    Think about Append Features to Layer as a Copy & Paste algorithm, which extracts features from a source vector layer and pastes them into an existing target vector layer.

    In fact, the algorithm is based on the Paste tool that QGIS offers in its main user interface, enabling you to use it in your Processing workflows.

  2. ETL (Extract, Transform and Load): (See example number 2)

    The Append Features to Layer algorithm acts as the 'Load' in an ETL operation. If you need to 'Transform' your features before using the 'Load', QGIS offers the Refactor fields algorithm.

    Using both algorithms in a model, you can create complex ETL processes to migrate entire data sets from a data structure into another. Fortunately, you can find such a model after installing this plugin!

  3. Send the output of a Processing algorithm to an existing layer:

    Unlike conventional QGIS Processing algorithms (except by in-place ones), Append Features to Layer allows you to store data into an existing target layer instead of into temporary layers.

    For instance, if you need to send the buffers of a point layer into an existing polygon layer, you can chain the Buffer and Append Features to Layer algorithms in the Processing modeler, so that the output from the buffer gets copied into your polygon layer.

  4. Update existing features in an existing (target) layer based on a source layer.

    The Append Features to Layer algorithm can search for duplicates while copying features from source to target layers. If duplicates are found, the algorithm can update the existing feature's geometry/attributes based on the source feature, instead of appending it. In other words, the algorithm performs an Upsert (Update or Insert a feature). You can find more details in the next section of this document.

  5. Update existing geometries in a (target) layer based on geometries from a source layer. ๐Ÿ†•

    The Append Features to Layer algorithm can search for duplicates while copying features from source to target layers. If duplicates are found, the algorithm can update the existing feature's geometry (leaving all feature attributes intact) based on the source feature's geometry, instead of appending it. In other words, the algorithm performs an Upsert (Update a geometry or Insert a feature). You can find more details in the next section of this document.

๐Ÿ› ๏ธ How does it work

Fields and geometries

Field mapping between source and target layers is handled automatically. Fields that are in both layers are copied. Fields that are only found in source are not copied to target layer.

Geometry conversion is done on the fly, if required by the target layer. For instance, single-part geometries are converted to multi-part if target layer handles multi-geometries; polygons are converted to lines if target layer stores lines; among others.

How the algorithm deals with duplicates

This algorithm allows you to choose a field in source and target layers to compare and detect duplicates. It has 4 modes of operation:

  1. APPEND new feature, regardless of duplicates.
  2. SKIP new feature if duplicate is found.
  3. UPDATE EXISTING FEATURE in target layer with attributes (including geometry) from the feature in the source layer.
  4. ONLY UPDATE EXISTING FEATURE's GEOMETRY in target layer (leaving its attributes intact) based on the feature's geometry in the source layer.

Note on Primary Keys

The algorithm deals with target layer's Primary Keys in this way:

PRIMARY KEY APPEND mode UPDATE mode
Automatic PK
(e.g., serial)
It lets the provider (e.g., PostgreSQL, GeoPackage, etc.) fill the value automatically It doesn't modify the value already stored
Non-automatic PK You need to provide a value for the PK in the source layer, because such value wil be set in the target layer's PK It doesn't modify the value already stored

Note on geometry updates

Mode UPDATE EXISTING FEATURE:

  • If target layer has geometries but input layer does not, then only attributes will be updated when a duplicate feature is found, i.e., the geometry in target layer will remain untouched.

๐Ÿ”Ž Where to find the algorithm

Once installed and activated, this plugin adds a new provider (ETL_LOAD) to QGIS Processing. You can find the Append Features to Layer algorithm in the Processing Toolbox, under ETL_LOAD -> Vector table -> Append features to layer.

image

๐Ÿ“ Examples

  1. Copy & Paste features

  2. ETL (Extract, Transform and Load):

    This plugin also installs 2 Processing models that chain Refactor Fields and Append features to layer algorithms. You can find the models under Models --> ETL_LOAD.

    The models allow you to

    i) Transform and Load (APPEND) all features from the source layer, or

    ETL-basic-model-append

    ETL-basic-model_dialog_append

    ii) Transform and Load (UPDATE) all features from the source, updating those features that are duplicate.

    ETL-basic-model-update

    ETL-basic-model_dialog_update

๐Ÿ Using Append Features to Layer in standalone PyQGIS scripts

Chances are you'd like to run this plugin from a PyQGIS script that works out of a QGIS GUI session. For that, take "Using QGIS Processing algorithms from PyQGIS standalone scripts" into account, as well as the following code snippet.

# Add the path to QGIS plugins so that you can import AppendFeaturesToLayer
# See paths in https://gis.stackexchange.com/questions/274311/274312#274312
sys.path.append(path_to_qgis_plugins)

from AppendFeaturesToLayer.processing.etl_load_provider import ETLLoadAlgorithmProvider

# Register the processing provider
provider = ETLLoadAlgorithmProvider()
qgis.core.QgsApplication.processingRegistry().addProvider(provider)

# Finally, enjoy!
result = processing.run("etl_load:appendfeaturestolayer",
                        {'SOURCE_LAYER': source_layer,
                         'SOURCE_FIELD': '',
                         'TARGET_LAYER': target_layer,
                         'TARGET_FIELD': '',
                         'ACTION_ON_DUPLICATE': 0})  # NO_ACTION: 0
                                                     # SKIP_FEATURE: 1
                                                     # UPDATE_EXISTING_FEATURE: 2
                                                     # ONLY_UPDATE_EXISTING_FEATURES_GEOMETRY: 3

The algorithm outputs are:

  • TARGET_LAYER
  • APPENDED_COUNT
  • SKIPPED_COUNT
  • UPDATED_FEATURE_COUNT
  • UPDATED_ONLY_GEOMETRY_COUNT ๐Ÿ†•

โš™๏ธ Using Append Features to Layer via QGIS Process

If you'd like to run the plugin without GUI, but don't want to deal with PyQGIS scripts, you can use QGIS Process. You run QGIS Process from the operating system's terminal, in this way:

$ qgis_process run "etl_load:appendfeaturestolayer" -- SOURCE_LAYER=/tmp/source.shp TARGET_LAYER=/tmp/target.shp ACTION_ON_DUPLICATE=0

Where NO_ACTION: 0, SKIP_FEATURE: 1, UPDATE_EXISTING_FEATURE: 2, ONLY_UPDATE_EXISTING_FEATURES_GEOMETRY: 3

Make sure the plugin can be found in your QGIS plugins folder, that is, that you have installed the plugin in your QGIS.

๐Ÿ’ป Running Unit Tests Locally

First, you need to set 2 environment variables:

export GITHUB_WORKSPACE=/path/to/AppendFeaturesToLayer/
export QGIS_TEST_VERSION="final-3_28_13"  # "final-3_34_1" for next LTR 

After that, you could run unit tests locally with this command:

docker-compose -f .docker/docker-compose.yml run --rm qgis

You could rebuild the Docker image in this way:

docker-compose -f .docker/docker-compose.yml down --rmi local && docker-compose -f .docker/docker-compose.yml build

appendfeaturestolayer's People

Contributors

gacarrillor avatar janzandr avatar mrchebur avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

appendfeaturestolayer's Issues

QGIS Crash

Hi Team,

QGIS is crashing while using this feature. I have around 35 mif files exported from AutoCAD, trying to append the data in mif files to the respective Geo packages. I have same number of Geo packages created in QGIS, have mapped the source and target layers and exported to JSON format. When I open it and run in batch mode QGIS crashes where as the same functionality is working fine if I run file by file and need help in the same. Please let me know for any other information.

Please add option to clear the target before insert

For ETL it can be useful to clear the destination before inserting.
Then we can do load, transform and dump the result.

For some processing i don't want to do upsert kind of insertion.
Just a plain clear the target and insert is also very usefull.

Points no longer show up after updating existing feature

I'm using this plugin to add addresses to an existing field in my layer. The points were all loaded in weeks ago with the "address" field left blank, and I am updating the "address" field as we get new batches of data (about a quarter of the points each time). I nearly got the result I was looking for, but had a hiccup at the end. When I appended the source layer to the target layer and selected "If duplicate is found, UPDATE existing feature", the addresses populated in the correct fields. But when I closed the attribute table, all of the updated points had disappeared from the map. Trying to select one in the attribute table and 'zoom to selection' gave me a "no extent could be determined" error. The points still had their latitude and longitude coordinates in the attribute table, but would no longer show up anywhere on the map.
Updating the extents of geometry in the properties had no effect, and the CSV I used has no geometry (attribute only).

option to select fields to update

Hi,
Nice plugin. Updating an existing layer with data from another layer seems to be a normal usecase, but I need to create all kinds of queries when I want to do this via field calculator.

Do I understand correctly that this plugin updates ALL fields that have the same fieldname in both target en source layer?
If so, It would be very nice to have a selectbox where I can select which fields in the target layer to update. If my source layer has 20 fields of which only 2 contain new data and the rest are empty (or contain old data), they will overwrite the target layer, thus perhaps emptying fields in the target layer which should have been kept.

The workaround is to prep my source layer to only contain the fields with updated data.

QGIS Crash

I am trying to append layers between two geopackages - same structure - but it is causing a QGIS crash. Any thoughts?

Seems to run the append, then crashes. See stack trace below,

Cheers Grant

Report Details

Python Stack Trace

Windows fatal exception: access violation

Thread 0x00000f98 (most recent call first):
  File "C:\OSGeo4W/apps/qgis/./python\qgis\core\additions\edit.py", line 43 in __exit__
    if not self.layer.commitChanges():
  File "C:\Users/Grant/AppData/Roaming/QGIS/QGIS3\profiles\Grant/python/plugins\AppendFeaturesToLayer\processing\algs\AppendFeaturesToLayer.py", line 344 in processAlgorithm
    target.endEditCommand()

Current thread 0x000050d8 (most recent call first):
  File "C:\OSGeo4W/apps/qgis/./python/plugins\processing\ProcessingPlugin.py", line 432 in executeAlgorithm
    dlg.exec_()
  File "C:\OSGeo4W/apps/qgis/./python/plugins\processing\gui\ProcessingToolbox.py", line 232 in executeAlgorithm
    self.executeWithGui.emit(alg.id(), self, self.in_place_mode, False)

Stack Trace


CPLODBCDriverInstaller::RemoveDriver :
QgsOgrProviderUtils::GDALOpenWrapper :
QgsPrecalculatedTextMetrics::count :
QgsOgrProviderUtils::wildcards :
QgsPrecalculatedTextMetrics::count :
QgsVectorLayerFeatureSource::QgsVectorLayerFeatureSource :
QgsVectorLayerProfileResults::visitFeaturesInRange :
QgsVectorLayer::createMapRenderer :
QgsMapRendererJob::prepareJobs :
QgsMapRendererParallelJob::startPrivate :
QgsMapCanvas::refreshMap :
QObject::qt_static_metacall :
QTimer::timerEvent :
QObject::event :
QApplicationPrivate::notify_helper :
QApplication::notify :
QgsApplication::notify :
QCoreApplication::notifyInternal2 :
QEventDispatcherWin32Private::sendTimerEvent :
QEventDispatcherWin32::event :
QApplicationPrivate::notify_helper :
QApplication::notify :
QgsApplication::notify :
QCoreApplication::notifyInternal2 :
QCoreApplicationPrivate::sendPostedEvents :
qt_plugin_query_metadata :
QEventDispatcherWin32::processEvents :
qt_plugin_query_metadata :
QEventLoop::exec :
QDialog::exec :
PyInit_QtWidgets :
PyArg_ParseTuple_SizeT :
PyEval_EvalFrameDefault :
PyObject_GC_Del :
PyFunction_Vectorcall :
PyFloat_FromDouble :
PyVectorcall_Call :
PyObject_Call :
PyInit_QtCore :
PyInit_QtCore :
PyInit_QtCore :
PyInit_QtCore :
PyInit_QtCore :
PyInit_QtCore :
QObject::qt_static_metacall :
QMetaObject::activate :
PyInit_QtCore :
PyInit_QtCore :
PyType_GenericNew :
PyEval_EvalFrameDefault :
PyFunction_Vectorcall :
PyFloat_FromDouble :
PyVectorcall_Call :
PyObject_Call :
PyInit_QtCore :
PyInit_QtCore :
PyInit_QtCore :
PyInit_QtCore :
QObject::qt_static_metacall :
QAbstractItemView::doubleClicked :
QTreeView::mouseDoubleClickEvent :
PyInit__gui :
QWidget::event :
QFrame::event :
QAbstractItemView::viewportEvent :
PyInit__gui :
QCoreApplicationPrivate::sendThroughObjectEventFilters :
QApplicationPrivate::notify_helper :
QApplication::notify :
QgsApplication::notify :
QCoreApplication::notifyInternal2 :
QApplicationPrivate::sendMouseEvent :
QSizePolicy::QSizePolicy :
QSizePolicy::QSizePolicy :
QApplicationPrivate::notify_helper :
QApplication::notify :
QgsApplication::notify :
QCoreApplication::notifyInternal2 :
QGuiApplicationPrivate::processMouseEvent :
QWindowSystemInterface::sendWindowSystemEvents :
QEventDispatcherWin32::processEvents :
qt_plugin_query_metadata :
QEventLoop::exec :
QCoreApplication::exec :
main :
BaseThreadInitThunk :
RtlUserThreadStart :

QGIS Info
QGIS Version: 3.34.2-Prizren
QGIS code revision: 7d199797fc
Compiled against Qt: 5.15.3
Running against Qt: 5.15.3
Compiled against GDAL: 3.8.2
Running against GDAL: 3.8.2

System Info
CPU Type: x86_64
Kernel Type: winnt
Kernel Version: 10.0.19045

Adding location proximity with fuzzy match.

We all have encountered that many time dealing with point data like poi , admin points from multiple sources have duplicates. To append them with existing data we have two challenges geom and name could be slightly different.

So we need fuzzy and distance proximity at the same time.

Currently most people use postgis or python queries to find duplicates but i haven't come accross a tool which can achieve such results.

If needed i would provide you with python script to do the task but have no idea how it works in a plugin. Happy to help .

Check for conflicts / duplications [Feature request]

I have just found this plugin and it is really useful for inserting additional records in Geopackage layers, and probably other database types. THANKS!

I would like to suggest a feature to check if the record exists - I have a table that has an 'external key' / foreign key that corresponds with the data that I am trying to append and it would be great if the I could select a column in the two layers for the plugin to check 'if exists'. If the plugin could exclude the existing rows, and only append new rows that would be fantastic.

Batch mode leads to crash

I have mapped all my source and target features in the Append Feature to Layer UI and generated the JSON file and saved it. QGIS is crasing when I tried to execute it in batch mode, however the single layer process is working fine.
AppendFeaturesToLayer 1.5.0, QGIS 3.32.1-Lima on Windows 10

Need more ways to find duplicates

It would be useful to expand the ability to search for duplicates by:

  • geometry;
  • several fields at the same time (e.g. by geometry and creation date).

Thank you for the plugin, it is very useful.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.