การระบุฟิลด์การเข้าร่วมในโปรแกรมเป็นแบบ ArcMap?


9

เป็นไปได้หรือไม่ที่จะระบุเขตข้อมูลการเข้าร่วมทางโปรแกรมที่ใช้กับตารางเข้าร่วมสองชุดข้อมูลเข้าด้วยกันใน ArcMap ขณะนี้ฉันกำลังใช้ ArcGIS 10.0, SP5 และต้องการโซลูชัน ArcPyแต่ฉันจะไม่คัดค้านโซลูชันอื่น ๆ หากไม่มีโซลูชัน ArcPy

วิธีหนึ่งที่ฉันลองใช้คือวนลูปผ่านทุกฟิลด์และมองหา "baseName" ที่ตรงกัน แต่นั่นเป็นเพียง "การศึกษาที่เดาได้" ที่คุณหวังว่าชื่อฟิลด์ในฐานข้อมูลทั้งสองจะเหมือนกัน

สำหรับการแสดงกราฟิกของสิ่งที่ฉันเป็นหลังจากนั้นฉันต้องการระบุ "อินพุตเข้าร่วมฟิลด์" และ "เอาท์พุทเข้าร่วมฟิลด์" ตามที่เห็นในกล่องโต้ตอบ "เพิ่มเข้าร่วม" แต่แน่นอนหลังจากที่จริงแล้ว

จะระบุ "ฟิลด์เข้าร่วมอินพุต" และ "ฟิลด์เข้าร่วมส่งออก" ได้อย่างไร

นี่เป็นคำถามเกี่ยวกับแท็กที่สามารถตรวจพบ“ เข้าร่วม” โดยทางโปรแกรมหรือไม่ แต่ในกรณีนี้ฉันต้องการขยายฟังก์ชั่นเพื่อระบุ FIELD (s) ที่ใช้ในการเข้าร่วมชุดข้อมูลสองชุด (หรือมากกว่า) เข้าด้วยกัน


คุณกำลังใช้ ArcGIS เวอร์ชันใดอยู่ และฉันคิดตามแท็กที่คุณกำลังมองหาวิธีการทำเช่นนี้กับ arcpy และไม่ใช่ ArcObjects?
blah238

ฉันกำลังใช้ ArcGIS 10.0, SP5 และใช่ฉันกำลังมองหา / หวังว่าจะแก้ปัญหา ArcPy แต่ฉันจะไม่ต่อต้านการแก้ปัญหา ArcObjects ถ้านั่นเป็นทางเลือกเดียว
RyanKDalton

1
นี่คือบางส่วนเอกสารที่หลงระเริง : edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriGeoDatabase/ ......มันเกี่ยวข้องกับ pRelClass นี่คือ RelationshipClass ที่ใช้เพื่อกำหนดตารางการเข้าร่วมและเขตข้อมูลเข้าร่วมเช่นเดียวกับ cardinality เมธอด Open สร้าง RelQueryTable ใหม่หรือส่งคืนการอ้างอิงไปยัง RelQueryTable ที่มีอยู่ถ้าคลาสนั้นถูกสร้างขึ้นแล้ว คุณสามารถเรียกใช้วิธีนี้และค้นหาการอ้างอิงที่เกี่ยวข้องกับ thepRelClass
lewis

@lewis คุณไม่จำเป็นต้องใช้วัตถุจากโรงงานเพื่อรับการอ้างอิงถึง RelQueryTable ที่มีอยู่ - ดูคำตอบของฉัน
blah238

คำตอบ:


8

นี่คือวิธีการ ArcObjects ตามตัวอย่างนี้เพื่อระบุการรวมทั้งหมดในเลเยอร์และระบุปลายทางและชื่อตารางต้นทางและคีย์หลักและกุญแจต่างประเทศ:

  1. รับการอ้างอิงไปยังILayerที่มีหนึ่งหรือมากกว่าเข้าร่วม
  2. ส่งILayerให้กับIDisplayTable
  3. ร่ายIDisplayTable.DisplayTableทรัพย์สินไปIRelQueryTable
  4. ในขณะที่ตารางปัจจุบันคือIRelQueryTable:
    1. ตรวจสอบRelQueryTableของDestinationTableและSourceTableคุณสมบัติ
    2. ตรวจสอบOriginPrimaryKeyและOriginForeignKeyคุณสมบัติของIRelQueryTable.RelationshipClassคุณสมบัติ
    3. ตั้งค่าตารางปัจจุบันRelQueryTableเป็นSourceTableคุณสมบัติปัจจุบัน

สคริปต์ Python นี้ (ใช้comtypesและโมดูลตัวช่วยนี้) จะเข้าร่วมการเชื่อมต่อทั้งหมดตั้งแต่ล่าสุดจนถึงเร็วที่สุดและพิมพ์ชื่อปลายทางและชื่อตารางต้นทางคีย์หลักต้นกำเนิดและ foreign key สำหรับการเข้าร่วมแต่ละครั้ง:

from ESRICOMHelpers import * # helper module from https://gis.stackexchange.com/a/5082/753
esriArcMapUI = GetESRIModule("esriArcMapUI")
esriCarto = GetESRIModule("esriCarto")
esriGeoDatabase = GetESRIModule("esriGeoDatabase")

def listJoins(table):
    while CType(table, esriGeoDatabase.IRelQueryTable):
        relQueryTable = CType(table, esriGeoDatabase.IRelQueryTable)
        destTable = relQueryTable.DestinationTable
        sourceTable = relQueryTable.SourceTable
        destDataset = CType(destTable, esriGeoDatabase.IDataset)
        sourceDataset = CType(sourceTable, esriGeoDatabase.IDataset)
        relClass = relQueryTable.RelationshipClass
        print destDataset.Name, sourceDataset.Name, relClass.OriginPrimaryKey, relClass.OriginForeignKey
        table = sourceTable

if __name__ == "__main__":
    #app = GetCurrentApp() # Use if run in-process
    app = GetApp("ArcMap") # Use if run in a standalone script
    mxd = CType(app.Document, esriArcMapUI.IMxDocument)

    # Gets the first layer in the active data frame
    map = mxd.FocusMap
    lyr = map.Layer[0]

    # Need to get the "display table" to access the joins
    displayTable = CType(lyr, esriCarto.IDisplayTable).DisplayTable

    # List the layer's joined tables
    listJoins(displayTable)

ตัวอย่างเอาต์พุตรับเลเยอร์ซอร์สที่มีสามตัวรวม:

join_table_3 master_fc_join_table_1_join_table_2 JOIN_ID_3 master_fc.MASTER_ID
join_table_2 master_fc_join_table_1 JOIN_ID_2 master_fc.MASTER_ID
join_table_1 master_fc JOIN_ID_1 MASTER_ID

สำหรับข้อมูลเพิ่มเติมให้ดูที่ฉันจะเข้าถึง ArcObjects จาก Python ได้อย่างไร


สิ่งนี้ดูมีแนวโน้มมาก ฉันมีแพคเกจ comtypes การติดตั้งและรหัสฟังก์ชั่นผู้ช่วยเพิ่ม "global name 'esriGeoDatabase' is not defined"แต่ฉันได้รับข้อผิดพลาด สถานที่ / ควรกำหนดไว้ในรหัสนำหน้าบรรทัดได้while CType(table, esriGeoDatabase.IRelQueryTable)อย่างไร
RyanKDalton

ฉันไม่ได้รวมไว้ แต่ในบางจุดคุณต้องนำเข้า comtypes wraps รอบ ๆ ไลบรารีวัตถุ ESRI ที่คุณต้องการ esriGeoDatabase = GetESRIModule("esriGeoDatabase")ใช้โมดูลผู้ช่วยของฉันมันเป็นง่ายๆเป็น
blah238

เข้าใจแล้วขอบคุณ มันจะใช้ได้กับเลเยอร์ใน ArcMap ด้วยหรือไม่ ฉันส่งแต่ละเลเยอร์จากlayerList = arcpy.mapping.ListLayers(mxd)ลงในlistJoins(table)โค้ด แต่มันข้ามไปที่whileคำสั่ง
RyanKDalton

ฉันไม่คิดว่าคุณสามารถส่งระหว่างวัตถุอาร์คpyและวัตถุ comtypes ดังนั้นคุณต้องได้รับการอ้างอิง ILayer ผ่าน ArcObjects ฉันได้อัปเดตรหัสเพื่อรวมตัวอย่างที่สมบูรณ์ยิ่งขึ้นแล้ว ควรใช้ทั้งในและนอกกระบวนการโดยการแสดงความคิดเห็น / ไม่แสดงความคิดเห็นในบรรทัดที่เกี่ยวข้อง
blah238

ใกล้ชิดขอบคุณสำหรับความอดทนในการเดินผ่าน ... ตอนนี้คุณจะส่งไฟล์เอกสารแผนที่ที่แท้จริง (* .mxd) ที่คุณต้องการดูได้อย่างไร app.Documentกลับมาพร้อมกับ'NoneType' object has no attribute 'Document'
RyanKDalton

1

ใส่ข้อมูลทั้งหมดของฟิลด์เป็นสตริง (หลังจากสั่งให้พวกเขา) เปรียบเทียบกับฟังก์ชั่น fuzzycompare และเลือกผู้ที่ให้การจับคู่ที่ดีที่สุดหรือจับคู่เบย์กับความแม่นยำแน่นอน

วิธีนี้คือเมื่อข้อมูลบางอย่างไม่พอดี หากคุณคิดว่าทั้งสองคอลัมน์จะพอดีกันเพียงแค่สั่งซื้อและเปรียบเทียบสำหรับการจับคู่ที่สมบูรณ์แบบกับฟังก์ชันเปรียบเทียบปกติ


0

ลองสิ่งนี้:

  • ใช้เครื่องมือการแปลง XSLTจากชุดเครื่องมือเมทาดาทาเพื่อเขียนไฟล์ข้อมูลเมตา xml / html สำหรับชุดข้อมูลที่เป็นปัญหา

    arcpy.XSLTransform_conversion(r'X:\temp\Scratch.gdb\fc_FeatureToPoint',"C:\Program Files\ArcGIS\Desktop10.1\Metadata\Stylesheets\ArcGIS.xsl", r'X:\temp\Metadata.html')
  • ใช้ตัวแยกวิเคราะห์ HTMLเพื่ออ่านในไฟล์เมตาดาต้าและค้นหาฟิลด์การเข้าร่วมจากประวัติการประมวลผลทางภูมิศาสตร์ของเครื่องมือฟิลด์การเข้าร่วม

  • เอาต์พุตตัวอย่างจากเครื่องมือการแปลง XSLT

เอาต์พุตจากเครื่องมือการแปลง XSLT


1
นั่นเป็นความคิดที่ฉลาดจริง ๆ ที่ฉันคิดว่ามีสัญญาที่แท้จริง แต่จากการทดสอบของฉันดูเหมือนว่ามันจะใช้ได้เฉพาะเมื่อไฟล์เข้าร่วมโดยใช้เครื่องมือ GP ที่เรียกว่า "JoinField" เนื่องจากนี่เป็นส่วนหนึ่งของประวัติศาสตร์กระบวนการ GP สำหรับชั้นนั้น หากผู้ใช้สร้างการเข้าร่วมผ่าน UI บรรทัดกระบวนการ JoinField จะไม่มีอยู่ในไฟล์เอาต์พุต ความคิดที่ดีแม้ว่า!
RyanKDalton

1
ฉันจะไม่พึ่งพาประวัติ GP สำหรับเรื่องนี้ เราพยายามที่จะลบมันโดยเร็วที่สุดเพราะสำหรับกระบวนการที่เกิดซ้ำมันจะทำการติดตั้งอย่างรวดเร็วในข้อมูลจำนวนมากที่ทำให้คลาสคุณลักษณะไม่สามารถใช้งานได้
blah238

-1

ชื่อตารางที่เข้าร่วมอยู่ในวัตถุ IFeatureLayer - IFeatureLayerDefinition เป็นสตริง .. ซึ่งฉันคิดว่าอาจมี SQL เข้าร่วมและทำให้ชื่อเขตข้อมูล

http://edndoc.esri.com/arcobjects/8.3/diagrams/Map%20Layer%20Object%20Model.pdf

หรือคุณหมายถึงถ้าคุณไม่สามารถเข้าถึงวัตถุนั้นได้?


IFeatureLayerDefinitionไม่มี "เข้าร่วม SQL" จะมีเพียงDefinitionExpressionคุณสมบัติที่เปิดเผยข้อความค้นหาคำจำกัดความของเลเยอร์คุณลักษณะหากตั้งค่าซึ่งเป็นส่วนคำสั่ง WHERE ที่ จำกัด แถวที่จะแสดง
blah238

อย่างไรก็ตามมีRelationshipClassสถานที่ให้บริการ แต่ฉันคิดว่านี่จะเปิดเผยการเข้าร่วมล่าสุดเท่านั้น คุณจะต้องใช้IRelQueryTableแทนเพื่อให้ได้ทั้งหมด
blah238

-2

เพื่อค้นหาฟิลด์ที่ตรงกันโดยไม่คำนึงถึงชื่อฟิลด์คุณสามารถทำสิ่งนี้:

import arcpy

fc = r"temp/RiversJoined.shp"

fldList1 = [f.name for f in arcpy.ListFields(fc)]
fldList2 =[g.name for g in arcpy.ListFields(fc)]

for f in fldList1:
    values1 = [f_row[0] for f_row in arcpy.da.SearchCursor(fc, (f))]
    for g in fldList2:
        values2 = [g_row[0] for g_row in arcpy.da.SearchCursor(fc,(g))]
        #compare field values
        #get names of matching fields
        if (fldList2.index(g) != fldList1.index(f) and values1 == values2):
            print "match: " + str(g) + " match: "+ str(f)

เฮ้กับใครก็ตามที่เคาะคำตอบของฉัน: คุณสามารถบอกฉันว่ามีอะไรผิดปกติกับคำตอบของฉัน? ขอบคุณ
mwil

1
ดูเหมือนว่าจะไม่ตอบคำถามตามที่ถาม เช่นเดียวกับคำตอบเปรียบเทียบคลุมเครือ เขตข้อมูลที่เหมือนกัน (หรือคล้ายกันเลือน) ไม่มีผลต่อการใช้งานจริงหรือไม่ในการเข้าร่วม
blah238
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.