Lewati ke isi
Profil penulisSeri Buku GIS Kehutanan dan Pertanian/ I3
Tampilkan bagian untuk:

BAB 3: Pilihan yang Dijaga: Domain Nilai dan Aturan Isian

#Studi kasus: "Satu kondisi, empat ejaan"

Kepala Seksi minta rekap jumlah pohon sehat. Anda mengelompokkan data survei berdasarkan kolom Kondisi, dan muncul tujuh baris, bukan tiga. Ada Sehat, sehat, dan Sehat (dengan spasi di ujung). Ada Terserang Hama dan Terserang hama. Dua baris lagi kosong.

Komputer menganggap semua ejaan itu berbeda. Rekap yang seharusnya selesai lima menit menjadi dua jam pembersihan. Bab ini mencegahnya sejak data dimasukkan.

#Konsep: domain dalam tiga kalimat

Domain adalah daftar nilai yang sah untuk satu kolom, seperti kotak pilihan di formulir kertas: surveyor tinggal mencentang, tidak mengetik bebas. Ada tiga bentuk umum: daftar (misalnya tiga kondisi pohon), rentang (tinggi pohon 0 sampai 60 m), dan pola teks. Domain mencegah salah ketik, tetapi tidak selalu menjadi gembok, dan di bab ini Anda akan melihat bedanya.

Istilah baru bagian ini:

  • Domain: daftar atau rentang nilai sah untuk satu kolom.
  • Value Map: pilihan tetap yang dibuat langsung di QGIS.
  • Value Relation: pilihan yang diambil dari sebuah tabel acuan.
  • Aturan isian (constraint): syarat sebuah isian, misalnya tidak boleh kosong.
  • Nilai bawaan: isian yang terisi otomatis, misalnya tanggal hari ini.
Ilustrasi 3.1: Domain sebagai penjaga pintu
Skema: nilai sehat huruf kecil ditolak karena tidak ada di daftar, sedangkan Sehat diterima

#Tiga lapis penjagaan

Banyak orang mengira satu pengaturan sudah cukup. Hasil uji saya menunjukkan ada tiga lapis, dengan kekuatan berbeda. [terbukti: diuji di QGIS 4.0.2 dan GDAL 3.12]

LapisDi mana tersimpanApa yang terjadi bila nilai salah
Domain di GeoPackageDi dalam berkas .gpkgQGIS membaca domain itu dan membuat kotak pilihan di formulir. Penulisan lewat program (GDAL atau skrip QGIS) tidak ditolak.
Pengaturan formulir QGIS (Value Map, Value Relation, Range, aturan isian)Di proyek, atau di dalam GeoPackage bila disimpan sebagai gayaFormulir mencegah isian yang salah dan memberi peringatan. Penulisan lewat program tidak melewati formulir.
Pagar di berkas (trigger SQL)Di dalam berkas .gpkgMenolak nilai salah, siapa pun yang menulis, termasuk skrip.

Jadi untuk survei lapangan yang melibatkan banyak orang, pakai lapis pertama dan kedua agar formulir ramah. Bila datanya penting sekali, tambahkan lapis ketiga.

#Memilih jenis pilihan

Ilustrasi 3.2: Tiga jenis domain
Skema: Value Map berupa daftar pendek tetap, Value Relation berupa daftar dari tabel acuan, Range berupa batas angka
  • Pakai Value Map untuk daftar pendek yang jarang berubah, seperti Kondisi.
  • Pakai Value Relation bila daftarnya bisa bertambah, seperti jenis pohon. Anda cukup menambah baris di tabel Ref_Jenis, tanpa mengutak-atik formulir.
  • Pakai Range untuk angka, seperti tinggi pohon 0 sampai 60 m.

#Aturan isian dan nilai bawaan

Aturan isian punya dua kekuatan. Yang tegas menolak penyimpanan. Yang lunak hanya memberi peringatan. Dalam skrip I3.4, saya memakai tegas untuk hal yang pasti salah, dan lunak untuk hal yang masih mungkin terjadi.

KolomAturanKekuatan
ID_SurveiTidak boleh kosong dan harus unikTegas
KondisiTidak boleh kosongTegas
Tinggi_PhnAntara 0 dan 60Tegas
Akurasi_mMaksimal 5 mLunak (peringatan)

Nilai bawaan menghemat waktu dan mengurangi salah ketik:

KolomEkspresi nilai bawaanHasil
Tgl_Surveito_date(now())Tanggal hari ini
Surveyor@user_account_nameNama akun yang sedang masuk
ID_SurveiEkspresi di Bagian ASV-001, lalu SV-002, dan seterusnya

Angka 5 m pada Akurasi_m adalah contoh. Tetapkan batas Anda sendiri dari uji titik referensi di Bab 1.

#Bagian A: QGIS

#Bagian A: Domain dan formulir di QGIS

Siapkan Survei_KPH.gpkg dari Bab 2 (atau jalankan skrip I3.2).

Lapis 1: domain di dalam GeoPackage

  1. Buka panel Browser. Klik kanan Survei_KPH.gpkg, lalu pilih New Field Domain ► New Coded Values Domain. Dokumentasi QGIS menyebut menu ini ada untuk GeoPackage dan file geodatabase. [CEK: isi kotak dialognya]
  2. Beri nama Kondisi_Pohon, tipe field Text, lalu isi tiga nilai: Sehat, Terserang Hama, Tebangan Liar.
  3. Buat satu lagi lewat New Field Domain ► New Range Domain: nama Tinggi_Pohon, tipe Decimal, nilai terkecil 0 dan terbesar 60. [CEK]
  4. Perluas Titik_Survei di Browser sampai terlihat daftar field. Klik kanan Kondisi, pilih Set Field Domain, lalu pilih Kondisi_Pohon. Ulangi untuk Tinggi_Phn dengan Tinggi_Pohon. [CEK]

Cara cepat dan terbukti: jalankan skrip I3.3. Hasil uji skrip (QGIS 4.0.2):

HASIL
Domain di berkas: ['Kondisi_Pohon', 'Tinggi_Pohon']
Widget Kondisi    : ValueMap
Widget Tinggi_Phn : Range
Nilai 'ngawur' dan tinggi 250 m: tertulis tanpa ditolak

Dua baris pertama membuktikan domain tersimpan dan QGIS membacanya. Baris terakhir membuktikan domain bukan gembok.

Lapis 2: formulir dan aturan isian

  1. Klik kanan Titik_Survei ► Properties ► tab Attributes Form. Pilih field Kondisi. Ubah Widget Type menjadi Value Map, lalu isi tiga pilihan tadi.
  2. Pilih Jenis. Ubah Widget Type menjadi Value Relation. Atur Layer ke Ref_Jenis, Key dan Value ke Jenis.
  3. Pilih Tinggi_Phn. Ubah Widget Type menjadi Range, lalu isi Minimum 0 dan Maximum 60.
  4. Pada Kondisi, centang Not null di bagian Constraints. Pada ID_Survei, centang Not null dan Unique. Pada Tinggi_Phn, isi Expression dengan "Tinggi_Phn" BETWEEN 0 AND 60, dengan pesan galat singkat. Centang Enforce expression constraint untuk aturan tegas.
  5. Pada bagian Defaults, isi Default value to_date(now()) untuk Tgl_Survei, dan @user_account_name untuk Surveyor.
  6. Simpan agar pengaturan ikut ke dalam GeoPackage. Di bawah jendela Properties, buka menu Style, lalu pilih penyimpanan gaya ke basis data (GeoPackage). [CEK: nama persis menu]

Semua ini juga bisa dikerjakan dengan skrip I3.4. Inti skrip:

PYTHON
# Inti skrip I3.4 (berkas lengkap: skrip/i3_04_formulir_widget.py)
widget("Kondisi", "ValueMap", {"map": [{p: p} for p in pilihan]})
widget("Jenis", "ValueRelation", {"Layer": ref_jenis.id(), "LayerName": "Ref_Jenis", "LayerSource": ref_jenis.source(),
                                  "LayerProviderName": "ogr", "Key": "Jenis", "Value": "Jenis", "AllowNull": False})
widget("Tinggi_Phn", "Range", {"Min": 0.0, "Max": 60.0, "Step": 0.1, "Style": "SpinBox", "Precision": 1, "AllowNull": False})
lyr.setConstraintExpression(idx("Tinggi_Phn"), '"Tinggi_Phn" BETWEEN 0 AND 60', "Tinggi pohon harus 0 sampai 60 m")
lyr.setFieldConstraint(idx("Tinggi_Phn"), QgsFieldConstraints.ConstraintExpression, QgsFieldConstraints.ConstraintStrengthHard)
lyr.setDefaultValueDefinition(idx("Tgl_Survei"), QgsDefaultValue("to_date(now())"))
lyr.saveStyleToDatabaseV2("Formulir_Survei", "Formulir survei pohon", True, "")

Ekspresi nilai bawaan untuk ID_Survei (menambah nomor terakhir dengan satu):

EKSPRESI
'SV-' || lpad(to_string(coalesce(maximum(to_int(substr("ID_Survei", 4))), 0) + 1), 3, '0')

Hasil uji skrip (QGIS 4.0.2):

HASIL
Simpan gaya ke GeoPackage: SaveStyleResult.Success
Gaya bawaan terbaca: True
Fitur salah : ['Kondisi: value is NULL', 'Tinggi_Phn: Tinggi pohon harus 0 sampai 60 m check failed',
               'Akurasi_m: Akurasi lebih dari 5 m: ulangi pengukuran bila bisa check failed']
Fitur benar : []
Tabel acuan ditemukan: Ref_Jenis
Nilai bawaan -> ID_Survei: SV-001 | Tgl_Survei: tanggal hari uji | Surveyor: nama akun

Fitur yang salah (kondisi kosong, tinggi 250 m, akurasi 8,4 m) ditandai tiga pelanggaran. Fitur yang benar lolos.

Lapis 3: pagar di berkas (opsional)

  1. Untuk data yang sangat penting, tambahkan trigger SQL. Skrip I3.5 memasang trigger pada salinan berkas dan menguji dua nilai:
SQL
CREATE TRIGGER cek_kondisi_tambah BEFORE INSERT ON Titik_Survei
WHEN NEW.Kondisi IS NULL OR NEW.Kondisi NOT IN ('Sehat','Terserang Hama','Tebangan Liar')
BEGIN SELECT RAISE(ABORT, 'Kondisi harus salah satu dari tiga pilihan baku'); END;
HASIL
Kondisi 'sehat' -> DITOLAK: Kondisi harus salah satu dari tiga pilihan baku
Kondisi 'Sehat' -> DITERIMA

#Bagian B: ArcGIS Pro

#Bagian B: ArcGIS Pro

Di geodatabase, domain adalah objek yang berdiri sendiri, lalu dipasang ke kolom. Alurnya tiga langkah. [kemungkinan: dokumentasi Esri]

  1. Create Domain (Data Management): pilih tipe Coded value atau Range.
  2. Add Coded Value To Domain atau Set Value For Range Domain: isi nilainya.
  3. Assign Domain To Field: pasang domain ke kolom.

Cara lewat antarmuka: pilih layer di panel Contents, tab Feature Layer ► Data ► Domains, klik New Domain, lalu simpan. Pasang domain di Fields view pada kolom Domain. Kolom Default di Fields view dipakai untuk nilai bawaan. [CEK]

PYTHON
# [CEK] Cocokkan dengan versi Anda. Nama alat dari dokumentasi ArcGIS Pro.
import arcpy
gdb = r"D:/KPH_Contoh/Survei.gdb"
arcpy.management.CreateDomain(gdb, "Kondisi_Pohon", "Kondisi pohon", "TEXT", "CODED")
for nilai in ["Sehat", "Terserang Hama", "Tebangan Liar"]:
    arcpy.management.AddCodedValueToDomain(gdb, "Kondisi_Pohon", nilai, nilai)
arcpy.management.CreateDomain(gdb, "Tinggi_Pohon", "Tinggi 0 sampai 60 m", "DOUBLE", "RANGE")
arcpy.management.SetValueForRangeDomain(gdb, "Tinggi_Pohon", 0, 60)
arcpy.management.AssignDomainToField(gdb + "/Titik_Survei", "Kondisi", "Kondisi_Pohon")
arcpy.management.AssignDomainToField(gdb + "/Titik_Survei", "Tinggi_Phn", "Tinggi_Pohon")

Padanan Value Relation: tidak ada yang persis sama di desktop. Cara umum adalah domain nilai kode yang diisi dari tabel acuan, lalu diperbarui dengan alat Table To Domain. [CEK]

Padanan aturan tegas di berkas: Attribute Rules (jenis constraint) di geodatabase, yang tidak dikenali ArcMap. [kemungkinan: dokumentasi Esri]

#Bagian C: ArcMap 10.8

#Bagian C: ArcMap 10.8

  1. Di jendela Catalog, klik kanan geodatabase ► Properties ► tab Domains. Buat domain, tentukan nama, tipe field, dan tipe domain (Coded Values atau Range). Isi nilainya. [kemungkinan: dokumentasi ArcMap]
  2. Pasang domain ke kolom lewat Feature Class Properties ► Fields, lalu pilih kolom dan atur Domain di bagian propertinya. [kemungkinan: dokumentasi ArcMap]
  3. Alat yang sama dengan Pro ada di ArcToolbox (Create Domain, Add Coded Value To Domain, Assign Domain To Field). Kode Python harus mengikuti Python 2.7. [CEK]

Tidak ada padanan: ArcMap tidak punya Value Relation, aturan isian ber-ekspresi, atau Attribute Rules. Pemeriksaan harus lewat skrip atau Bab 6. [kemungkinan]

#Cek paham

  1. Mengapa Value Relation lebih baik daripada Value Map untuk daftar jenis pohon?
  2. Apa beda aturan isian tegas dan lunak?
  3. Mengapa domain di GeoPackage belum menjamin tidak ada nilai salah?

Jawaban:

  1. Daftar jenis bisa bertambah. Dengan Value Relation, Anda cukup menambah baris di tabel acuan. Dengan Value Map, Anda harus mengubah pengaturan formulir.
  2. Tegas menolak penyimpanan. Lunak hanya memberi peringatan, sehingga data tetap bisa disimpan.
  3. Domain bekerja di formulir. Penulisan langsung lewat program tidak melewati formulir, sehingga nilai di luar daftar tetap bisa tertulis. Untuk jaminan kuat, perlu pagar di berkas atau pemeriksaan data berkala.

#Kesalahan umum

  • Mengetik pilihan manual di banyak tempat. Tempatkan daftar di satu tabel acuan dan pakai ulang.
  • Mengubah daftar setelah data terkumpul. Nilai lama yang tidak ada di daftar baru akan menjadi tidak sah. Ganti dengan hati-hati dan perbarui data lama.
  • Menyimpan formulir hanya di proyek. Ponsel yang memuat GeoPackage saja tidak melihat pengaturan itu. Simpan gaya ke dalam GeoPackage, atau bawa proyeknya.
  • Menganggap domain sama dengan gembok. Anggap domain sebagai penunjuk arah. Tetap periksa data (Bab 6).

#Ringkasan dan latihan

Ringkasan: domain membatasi pilihan satu kolom. Daftar tetap pakai Value Map, daftar yang bisa tumbuh pakai Value Relation, angka pakai Range. Aturan isian dan nilai bawaan melengkapinya. Penjagaan kuat butuh trigger atau pemeriksaan data.

Latihan: jalankan skrip I3.3 dan I3.4 pada Survei_KPH.gpkg. Lalu muat ulang berkas itu di proyek QGIS kosong, dan periksa apakah Kondisi tampil sebagai kotak pilihan. Tambahkan nilai keempat Lainnya ke tabel Ref_Kondisi. Mengapa nilai itu belum muncul di Value Map Kondisi?

Jawaban yang diharapkan: karena Kondisi memakai Value Map yang daftarnya tetap di pengaturan, bukan membaca tabel acuan.

#Tabel perbandingan: membatasi isian

TugasQGISArcGIS ProArcMap 10.8
Daftar pilihan tetapDomain di GeoPackage, atau Value MapCoded value domainCoded value domain
Daftar dari tabelValue RelationTable To Domain [CEK]Table To Domain [CEK]
Rentang angkaRange domain atau widget RangeRange domainRange domain
Tidak boleh kosong, unikConstraints di Attributes FormAllow NULL di Fields view; unik lewat aturan [CEK]Allow NULL di Fields
Aturan ber-ekspresiExpression constraintAttribute RulesTidak ada padanan
Nilai bawaanDefaults di Attributes FormKolom Default di Fields viewDefault value pada properti field
Penolakan di berkasTrigger SQLAttribute RulesTidak ada padanan