2010-06-26 26 views
5

Tôi đang xây dựng một ứng dụng quản lý để giúp quản lý công ty chi tiết tự động trên điện thoại di động của tôi (và hy vọng những người khác). Tôi đang đấu tranh để tìm ra cách mô hình hóa một số dữ liệu.Các cuộc hẹn và chi tiết đơn hàng

Câu hỏi này có liên quan đến một câu hỏi trước mà tôi đã đăng, nhưng tôi đã sao chép các thông tin liên quan dưới đây: Database design - google app engine

Trong ứng dụng này, có khái niệm về "cuộc hẹn" và "Line Items. "

Các cuộc hẹn là địa điểm và thời gian mà nhân viên dự kiến ​​sẽ cung cấp dịch vụ.

Chi tiết đơn hàng là dịch vụ, phí hoặc chiết khấu và thông tin liên quan của nó. Ví dụ về chi tiết đơn hàng có thể tham gia cuộc hẹn:

 
Name:       Price: Commission: Time estimate 
Full Detail, Regular Size:  160  75  3.5 hours 
$10 Off Full Detail Coupon:  -10  0   0 hours 
Premium Detail:     220  110  4.5 hours 
Derived totals(not a line item): $370  $185  8.0 hours 

Trong lần triển khai trước của ứng dụng này, Chi tiết đơn hàng được chứa trong một cuộc hẹn. Điều này làm việc tốt hầu hết thời gian, nhưng đôi khi gây ra vấn đề. Một ví dụ sẽ là nếu một cuộc hẹn bị gián đoạn một nửa vì mưa và kỹ thuật viên phải quay trở lại vào ngày hôm sau và kết thúc. Tình huống này yêu cầu hai cuộc hẹn cho cùng một chi tiết đơn hàng. Trong những trường hợp như thế này, tôi sẽ chỉ dịch chuyển dữ liệu một chút bằng cách đặt "mục hàng" trong cuộc hẹn thứ hai để đọc nội dung như "Hoàn thành" và sau đó chi phí sẽ là $ 0.

Trong phiên bản tiếp theo này, tôi đang xem xét tạo điều kiện cho dòng bài viết nào được xuất hiện với nhiều hơn một cuộc hẹn với một cấu trúc bảng trông như thế này:

Appointment 
start_time 
etc... 

Line_Item 
appointment_Key_List 
name 
price 
etc... 

Một vấn đề chung với cấu trúc này là nó là phức tạp và tôi thậm chí không chắc liệu nó có phù hợp để phù hợp với một mục hàng có nhiều cuộc hẹn hay không. Nếu Mục hàng chỉ có thể là một phần của một cuộc hẹn, thì tôi thực sự có thể chỉ cần đưa danh sách mục hàng vào mỗi cuộc hẹn, khi tôi nhận được cuộc hẹn, tôi đã nhận được mục hàng.

Một vấn đề cụ thể hơn là tôi đang sử dụng công cụ ứng dụng của Google và nếu tôi muốn truy vấn tập hợp các cuộc hẹn và mục hàng được liên kết của họ, tôi phải truy vấn đầu tiên cho các cuộc hẹn và sau đó thực hiện một giây truy vấn cho các mục hàng bằng cách sử dụng toán tử IN để kiểm tra xem có bất kỳ khóa cuộc hẹn của Line_Item nào rơi vào tập hợp các khóa cuộc hẹn được trả về từ truy vấn trước đó hay không. Truy vấn thứ hai sẽ thất bại nếu tôi có hơn 30 khóa yêu cầu tôi phân phát truy vấn. Tôi có thể không chuẩn hóa dữ liệu để tránh truy vấn đọc phức tạp và mở rộng này, và tôi có lẽ sẽ phải biến đổi bất thường ở mức độ nào đó, nhưng tôi muốn tránh sự phức tạp khi thích hợp.

Câu hỏi của tôi là loại tình huống này thường được mô hình hóa như thế nào? Thậm chí có thích hợp cho một Mục hàng được kết hợp với nhiều cuộc hẹn hay không, chỉ đơn giản là chia các chi tiết đơn hàng thành các mục riêng biệt cho mỗi cuộc hẹn như "nửa đầu của công việc 2 ngày" và "nửa sau của công việc hai ngày . " Làm thế nào để các ứng dụng thành công tương tự làm điều này? Quy tắc chung trong loại tình huống này là gì? Việc triển khai nào đã trở nên ít vấn đề hơn?

Cảm ơn!

Trả lời

2

Cách tiếp cận bạn đề xuất sẽ hoạt động tốt; bạn có thể lập mô hình 'date_Key_list' của chi tiết đơn hàng dưới dạng thuộc tính danh sách và nó sẽ hoạt động như bạn mong đợi. Bạn không phải sử dụng toán tử IN - đó là để khớp một giá trị duy nhất trong kho dữ liệu với danh sách các khóa bạn có (ví dụ: "WHERE datastore_column IN ('a', 'b', 'c')), trong khi

Tôi sẽ đề nghị, tuy nhiên, ngược lại có thể phù hợp hơn với nhiệm vụ của bạn: Yêu cầu mỗi cuộc hẹn đều có danh sách các phím mục hàng. Điều này hoạt động nhiều theo cùng một cách, nhưng để lấy tất cả dữ liệu về cuộc hẹn, trước tiên bạn tìm nạp cuộc hẹn, sau đó thực hiện số lượng lớn các mục hàng, sử dụng các phím từ thực thể Cuộc hẹn. , do đó, bạn không cần phải thực hiện bất kỳ truy vấn nào.

Tôi đã cố gắng giải thích cho Pindatjuh tại sao truy vấn một danh sách bất động sản không kém hiệu quả hơn một giá trị đơn lẻ, nhưng apparrently mô tả chi tiết hơn là cần thiết, do đó, không có thêm ado, ở đây là ...

một mồi ngắn gọn trên App Engine Datastore indexing

Mặc dù Python và Java cung cấp giao diện cấp cao khác nhau để các kho dữ liệu, kho dữ liệu riêng của mình nói một trừu tượng cấp dưới, được gọi là các thực thể. Một thực thể bao gồm các nội dung sau:

  1. Một độc đáo chính chủ chốt
  2. Một danh sách (tên, giá trị) cặp

Mấu chốt chính là chìa khóa Datastore bạn đã quen thuộc với. Danh sách các cặp (tên, giá trị) là biểu diễn của App Engine cho dữ liệu trong thực thể của bạn. Cho đến nay rất đơn giản. Một thực thể với các giá trị sau:

a_string = "Hello, world" 
an_int = 123 

sẽ tuần tự đến một cái gì đó giống như này:

[('a_string', 'Hello, world'), ('an_int', 123)] 

Nhưng làm thế nào thực hiện điều này tương tác với danh sách? Vâng, danh sách được coi là thuộc tính 'nhân giá trị'. Tức là, một danh sách có n mục được lưu trữ dưới dạng n thuộc tính riêng biệt. Một ví dụ có thể làm cho điều này rõ ràng hơn:

a_string = "Hello, world" 
an_int = 123 
a_list_of_ints = [42, 314, 9] 

sẽ được tuần tự như:

[('a_string', 'Hello, world'), ('an_int', 123), ('a_list_of_ints', 42), ('a_list_of_ints', 314), ('a_list_of_ints', 9)] 

Như bạn có thể thấy, danh sách được đại diện cho một loạt các giá trị, tất cả có cùng tên. Khi bạn tải dữ liệu từ kho dữ liệu, SDK sẽ thấy giá trị lặp lại và biến nó thành một danh sách.

Trường hợp này quan trọng là khi nó tương tác với lập chỉ mục. Giả sử bạn có chỉ mục trên 'a_string' và 'an_int'. Khi bạn chèn hoặc sửa đổi một giá trị, App Engine sẽ tạo ra một tập các mục chỉ mục cho nó; cho các chỉ số trên và các tổ chức trên, nó tạo ra một hàng duy nhất trong chỉ mục mà trông giống như sau:

('Hello, world', 123, a_key) 

('a_key' đây là một giữ chỗ cho chủ chốt của đơn vị gốc.) Khi bạn làm một truy vấn sử dụng chỉ mục này, nó chỉ cần thực hiện tìm kiếm trên chỉ mục để tìm các hàng có tiền tố thích hợp (Ví dụ: 'SELECT * FROM FROM WHERE a_string = "Hello, world" ORDER BY an_int').

Khi bạn lập chỉ mục danh sách, App Engine sẽ chèn nhiều hàng chỉ mục. Một chỉ mục trên 'an_int' và 'a_list_of_ints' sẽ tạo ra những hàng cho các tổ chức trên:

(123, 42, a_key) 
(123, 314, a_key) 
(123, 9, a_key) 

Một lần nữa, truy vấn hoạt động giống như nó đã làm trước đây - App Engine chỉ phải tìm kiếm hàng với tiền tố đúng trong chỉ mục. Số lượng các mục trong danh sách không có tác động đến tốc độ truy vấn - chỉ mất bao lâu để tạo và ghi các mục chỉ mục. Trên thực tế, trình lập kế hoạch truy vấn không có ý tưởng rằng 'a_list_of_ints' là một thuộc tính có giá trị nhân - nó chỉ xử lý nó giống như bất kỳ mục nhập chỉ mục nào khác.

Vì vậy, trong Tóm lại:

  1. Không có sự khác biệt thực tiễn giữa một danh sách với một yếu tố trong đó và một tài sản cá nhân, trong chỉ mục và thuật ngữ truy vấn
  2. Kích thước của một danh sách được lập chỉ mục ảnh hưởng đến thời gian và không gian cần thiết để lập chỉ mục, nhưng không phải để truy vấn.
  3. Bạn có thể thực hiện truy vấn khớp với bất kỳ thực thể nào có giá trị đã cho trong danh sách bằng bộ lọc bình đẳng đơn giản.
+0

Câu trả lời rất nhiều thông tin! Cảm ơn bạn đã chia sẻ thông tin này với SO. @DutrowLLC vui lòng đánh dấu câu trả lời này là câu trả lời chính xác, theo ý kiến ​​của tôi, một câu trả lời tốt hơn cho câu hỏi của bạn. @ Nick Johnson Tôi xin lỗi vì đã tin vào những thứ sai trái. Cảm ơn bạn đã giải thích và cung cấp câu trả lời rất hay này với thông tin tuyệt vời cho mọi người! – Pindatjuh

+0

@Pindatjuh - Rất nhiều thứ để tham gia. Video này cũng đi sâu vào một số chi tiết về cách danh sách được lập chỉ mục và tìm kiếm. Tôi tìm thấy nửa thứ hai trên hợp nhất tham gia cực kỳ hữu ích. Đó là bản pdf có trang trình bày mà bạn có thể xem trong khi xem video: http://code.google.com/events/io/2009/sessions/BuildingScalableComplexApps.html –

+0

Cảm ơn bạn đã dành thời gian trả lời câu hỏi này thật kỹ lưỡng , Tôi hy vọng những người khác cũng sẽ có thể tìm thấy câu trả lời của bạn và hưởng lợi từ nó. –

1

Giải pháp thông thường cho loại sự cố này là chuẩn hóa mô hình, ví dụ: First Normal Form.

Mô hình của bạn, ở dạng bình thường, sẽ có một bảng thứ ba, với tham chiếu đến các AppointmentLine_Item hàng:

Appointment 
start_time 
... 

Line_Item 
name 
price 
... 

Appointment_Line_Item 
appointment_key 
line_item_key 

Có một vấn đề tuy nhiên! Vì bạn đang sử dụng Google App Engine và Datastore của họ khá hạn chế ("GQL cannot perform an SQL-like JOIN") và hầu hết yêu cầu không chuẩn hóa.

Bạn đã đề xuất sử dụng trường giống như danh sách. Đó là khả năng sử dụng điều này, nhưng rất khó để lập chỉ mục nó. Tìm kiếm khóa (appointment_key) trong danh sách mỗi hàng trong cơ sở dữ liệu không thực sự hoạt động. Tôi đề xuất hai tài sản:

  1. Trùng lặp Line_Item.

    Line_Item 
    appointment_key 
    name 
    price 
    finished 
    ... 
    

    Một Line_Item nên có tình trạng finished, khi mục đã kết thúc hay không do người lao động. Nếu một nhân viên chưa hoàn thành tất cả các mục hàng, hãy đánh dấu chúng là chưa hoàn thành, tạo một cuộc hẹn mới và sao chép tất cả các mục chưa hoàn thành. Bạn có thể lập chỉ mục trên trường appointment_key trên tất cả Line_Items, đó là Điều tốt. Tuy nhiên, dữ liệu trùng lặp có thể là một vấn đề.

  2. lĩnh vực năng động cho Line_Item:

    Line_Item 
    duplicate_key 
    appointment_key 
    name 
    price 
    finished 
    ... 
    

    Tạo một lĩnh vực mới, duplicate_key, cho Line_Item mà điểm đến Line_Item khác hoặc null (dành phím này!). Null có nghĩa là Line_Item là bản gốc, bất kỳ giá trị nào khác có nghĩa là Line_Item này trùng lặp với trường Line_Item trỏ đến. Tất cả các trường của Line_Item được đánh dấu là trùng lặp kế thừa các trường của Line_Item ban đầu, ngoại trừ appointment_key: vì vậy sẽ mất ít bộ nhớ hơn. Ngoài ra giải pháp này nên có chỉ số appointment_key được lập chỉ mục, để tăng tốc thời gian tra cứu. Điều này yêu cầu một truy vấn bổ sung cho mỗi Line_Item trùng lặp, có thể là một vấn đề.

Bây giờ, đó là lựa chọn rõ ràng: tốc độ tốt hơn hoặc bộ nhớ tốt hơn. Tôi sẽ đi đầu tiên, vì nó làm giảm sự phức tạp của mô hình của bạn, và lưu trữ không bao giờ là vấn đề với các hệ thống hiện đại. Ít phức tạp hơn thường có nghĩa là ít lỗi hơn và chi phí phát triển/thử nghiệm ít hơn, điều này giải thích chi phí của yêu cầu lưu trữ.

+0

Cảm ơn phản hồi của bạn. Tôi chưa bao giờ nghĩ về cách tiếp cận khóa trùng lặp, đó là một giải pháp thực sự thú vị. Một điều cần ghi nhớ với công cụ ứng dụng là chúng lập danh sách chỉ mục và cho phép bạn tìm kiếm chúng. Họ gọi đó là "hợp nhất tham gia" và dường như mở rộng khả năng của mình ngoài cửa hàng khóa-giá trị đơn giản: http://code.google.com/events/io/2009/sessions/BuildingScalableComplexApps.html –

+1

"Tìm kiếm một khóa (các cuộc hẹn) trong một danh sách mỗi hàng trong cơ sở dữ liệu không thực sự thực hiện. " - không đúng. Bạn có thể lọc các thuộc tính danh sách trong App Engine cũng hiệu quả như trên các danh sách không phải. –

+0

@Nick Johnson - Cảm ơn bạn đã tham gia với điều đó. Tôi nghĩ rằng đó là một sự thay đổi trò chơi quan trọng với các công cụ ứng dụng đó là bất ngờ và không nổi tiếng. –

Các vấn đề liên quan