Lập trình xác định Trường tham gia trong ArcMap?


9

Có thể xác định theo chương trình Trường tham gia đang được sử dụng để Bảng nối hai bộ dữ liệu với nhau trong ArcMap không? Tôi hiện đang sử dụng ArcGIS 10.0, SP5 và muốn sử dụng giải pháp ArcPy , tuy nhiên tôi sẽ không phản đối các giải pháp khác, nếu không có giải pháp ArcPy.

Một phương pháp tôi đã thử là lặp qua tất cả các trường và tìm kiếm một "tên cơ sở" phù hợp, nhưng đó chỉ là một "phỏng đoán có giáo dục" mà bạn đang hy vọng rằng tên trường trong cả hai cơ sở dữ liệu đều giống nhau.

Để thể hiện đồ họa của những gì tôi đang theo đuổi, về cơ bản, tôi muốn xác định "Trường tham gia đầu vào" và "Trường tham gia đầu ra" như trong hộp thoại "Thêm tham gia", nhưng thực tế là vậy.

Làm cách nào để xác định "Trường tham gia đầu vào" và "Trường tham gia đầu ra"?

Đây là một câu hỏi gắn thẻ để Có thể phát hiện ra một người tham gia chương trình có thể lập trình được không? , nhưng trong trường hợp này tôi muốn mở rộng chức năng để xác định (các) FIELD đang được sử dụng để nối hai (hoặc nhiều) bộ dữ liệu lại với nhau.


Phiên bản nào của ArcGIS mà bạn đang làm việc? Và tôi giả sử dựa trên các thẻ mà bạn đang tìm kiếm cụ thể để làm điều này với Arcpy và không phải ArcObjects?
blah238

Tôi hiện đang sử dụng ArcGIS 10.0, SP5. Và vâng, tôi đang tìm kiếm / hy vọng cho một giải pháp ArcPy, tuy nhiên tôi sẽ không phản đối giải pháp ArcObjects, nếu đó là giải pháp thay thế duy nhất.
RyanKDalton

1
Dưới đây là một số tài liệu có thể Revelant: edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriGeoDatabase/... Nó liên quan đến việc pRelClass Đây là RelationshipClass dùng để xác định tham gia bàn và tham gia các lĩnh vực cũng như cardinality. Phương thức mở hoặc tạo một RelQueryTable mới hoặc trả về một tham chiếu đến RelQueryTable hiện có nếu lớp đó đã được tạo. Bạn có thể gọi phương thức này và tìm tham chiếu liên quan đến thepRelClass
lewis

@lewis, bạn không cần sử dụng đối tượng nhà máy để có được tham chiếu đến RelQueryTable hiện tại - xem câu trả lời của tôi.
blah238

Câu trả lời:


7

Dưới đây là cách tiếp cận ArcObjects, dựa trên ví dụ này , để liệt kê tất cả các phép nối trên một lớp và liệt kê tên bảng đích và bảng nguồn của chúng và các khóa chính và khóa ngoài:

  1. Nhận một tham chiếu đến một ILayercó một hoặc nhiều tham gia
  2. Cast ILayerđểIDisplayTable
  3. Đúc IDisplayTable.DisplayTabletài sản đểIRelQueryTable
  4. Trong khi bảng hiện tại là IRelQueryTable:
    1. Kiểm tra việc RelQueryTable's DestinationTableSourceTablethuộc tính
    2. Kiểm tra OriginPrimaryKeyOriginForeignKeycác tài sản của IRelQueryTable.RelationshipClasstài sản.
    3. Đặt bảng hiện nay với dòng RelQueryTable's SourceTabletài sản

Tập lệnh Python này (sử dụng comtypesmô đun trình trợ giúp này ) sẽ đi qua tất cả các phép nối, từ mới nhất đến sớm nhất và in tên bảng đích và nguồn, khóa chính gốc và khóa ngoại gốc cho mỗi phép nối:

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)

Ví dụ đầu ra, được cung cấp một lớp nguồn với ba phép nối:

tham gia_table_3 master_fc_join_table_1_join_table_2 THAM GIA_ID_3 master_fc.MASTER_ID
tham gia_table_2 master_fc_join_table_1 THAM GIA_ID_2 master_fc.MASTER_ID
tham gia_table_1 master_fc THAM GIA_ID_1 MASTER_ID

Để biết thêm thông tin, hãy xem Làm cách nào để tôi truy cập ArcObjects từ Python?


Điều này có vẻ rất hứa hẹn. Tôi đã cài đặt gói comtypes và thêm mã chức năng của trình trợ giúp, nhưng tôi gặp lỗi "global name 'esriGeoDatabase' is not defined". Ở đâu / Làm thế nào nó nên được xác định trong mã trước dòng while CType(table, esriGeoDatabase.IRelQueryTable)?
RyanKDalton

Tôi đã không bao gồm nó, nhưng tại một số điểm bạn phải nhập các trình bao bọc comtypes xung quanh các thư viện đối tượng ESRI cụ thể mà bạn cần. Sử dụng mô đun trợ giúp của tôi, nó đơn giản như esriGeoDatabase = GetESRIModule("esriGeoDatabase").
blah238

Hiểu rồi, cảm ơn. Điều này cũng sẽ làm việc cho các lớp trong ArcMap chứ? Tôi đang đi qua từng lớp từ layerList = arcpy.mapping.ListLayers(mxd)vào listJoins(table)mã, nhưng nó bỏ qua hiện tại whiletuyên bố.
RyanKDalton

Tôi không nghĩ rằng bạn có thể truyền giữa các đối tượng Arcpy và các đối tượng comtypes, vì vậy bạn cần có được tham chiếu ILayer thông qua ArcObjects. Tôi đã cập nhật mã để bao gồm một ví dụ đầy đủ hơn. Điều này sẽ có thể được sử dụng cả trong và ngoài quá trình bằng cách bình luận / bỏ ghi chú các dòng liên quan.
blah238

Đến gần hơn, cảm ơn vì sự kiên nhẫn trong suốt ... bây giờ, làm thế nào để bạn gửi tệp tài liệu bản đồ thực tế (* .mxd) mà bạn muốn xem? app.Documenttrở lại với'NoneType' object has no attribute 'Document'
RyanKDalton

1

Đặt tất cả dữ liệu của các trường trong chuỗi, (sau khi đã đặt hàng chúng) so sánh chúng với hàm fuzzycompare và chọn những người đưa ra kết quả khớp tốt nhất hoặc khớp với độ chính xác nhất định.

Giải pháp này là khi một số dữ liệu không phù hợp. Nếu bạn nghĩ rằng cả hai cột sẽ luôn phù hợp, thì chỉ cần đặt hàng và so sánh cho một kết hợp hoàn hảo với một chức năng so sánh thông thường.


0

Thử đi:

  • Sử dụng công cụ Chuyển đổi XSLT từ bộ công cụ Siêu dữ liệu để viết ra tệp siêu dữ liệu xml / html cho tập dữ liệu được đề cập.

    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')
  • Sử dụng trình phân tích cú pháp HTML để đọc trong tệp siêu dữ liệu và tìm kiếm trường tham gia từ lịch sử xử lý địa lý của công cụ Tham gia

  • Đầu ra mẫu từ công cụ Chuyển đổi XSLT

Đầu ra từ công cụ Chuyển đổi XSLT


1
Đó là một ý tưởng thực sự thông minh mà tôi nghĩ đã có lời hứa thực sự, nhưng từ thử nghiệm của tôi, dường như điều này sẽ chỉ hoạt động nếu tệp được tham gia bằng Công cụ GP có tên là "JoinField", vì đây được viết như một phần của lịch sử quy trình GP cho lớp đó Nếu người dùng đã tạo liên kết thông qua giao diện người dùng, dòng quy trình JoinField không tồn tại trong tệp đầu ra. Ý tưởng tuyệt vời mặc dù!
RyanKDalton

1
Tôi sẽ không dựa vào lịch sử GP cho dù sao đi nữa. Chúng tôi cố gắng xóa nó càng sớm càng tốt vì đối với các quy trình định kỳ, nó sẽ nhanh chóng gắn kết với một lượng dữ liệu khổng lồ làm cho một lớp tính năng gần như không thể sử dụng được.
blah238

-1

Tên bảng đã tham gia nằm trong đối tượng IFeatureLayer - IFeatureLayerDefDef dưới dạng chuỗi .. mà tôi nghĩ có thể chứa SQL tham gia và do đó là tên trường.

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

Hay bạn có nghĩa là nếu bạn không thể truy cập vào đối tượng đó?


IFeatureLayerDefinitionkhông chứa "SQL tham gia", nó chỉ có một DefinitionExpressionthuộc tính hiển thị truy vấn định nghĩa của lớp tính năng, nếu được đặt, đó là mệnh đề WHERE giới hạn các hàng được hiển thị.
blah238

RelationshipClassTuy nhiên, nó có một tài sản, nhưng tôi nghĩ rằng điều này chỉ làm lộ ra sự tham gia gần đây nhất. Bạn sẽ cần phải sử dụng IRelQueryTablethay thế để có được tất cả.
blah238

-2

để tìm các trường khớp bất kể tên trường, bạn có thể làm một cái gì đó như thế này:

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)

này để bất cứ ai gõ câu trả lời của tôi: bạn có thể cho tôi biết những gì sai với câu trả lời của tôi? cảm ơn.
mwil

1
Điều này không xuất hiện để trả lời câu hỏi như đã hỏi. Tương tự với câu trả lời so sánh mờ. Các trường giống hệt nhau (hoặc thậm chí tương tự mờ) không liên quan đến việc chúng có thực sự được sử dụng trong một phép nối hay không.
blah238
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.