2012-06-13 38 views
6

Tôi có bộ sưu tập sự kiện mà tôi sẽ tìm kiếm để tìm một sự kiện cụ thể và sau đó tôi đang cập nhật bộ sưu tập khác của mình bằng cách sử dụng $ push tuyên bố. Vấn đề là khi hai sự kiện có cùng một danh mục nó sẽ tạo ra một bản sao, mà tôi không muốn.Đẩy phần tử vào một mảng nếu nó không có mặt (không trùng lặp)

Tôi biết về upserts nhưng tôi không chắc chắn nếu họ là cách tốt nhất để đi về việc này? Và tôi là một chút bối rối khi nói đến cách thực sự viết một upsert mà làm việc với "$ đẩy" -statement.

Đây là cách cập nhật của tôi trông ngay bây giờ:

self.users.update({"user_id": event['userid']}, {'$push': {'campaigns': UserCampaign}}) 

..where:

UserCampaign = { 
     "id": campaign['id'], 
     "name": campaign['name'] 
} 

Các "UserCampaign" được lấp đầy với các thông tin tương tự theo thời gian, và vì tôi bộ sưu tập có lẽ sẽ rất lớn tôi muốn hoàn thành điều này càng hiệu quả càng tốt.

TLDR; Tôi muốn cập nhật mảng trong tài liệu được tìm thấy bằng cách sử dụng "đẩy" mà không có nguy cơ bị trùng lặp.

Trả lời

11

Tìm thấy một câu trả lời tốt hơn cho vấn đề của tôi:

Bằng cách sử dụng $ addToSet nó không tạo ra các bản sao (Tôi cũng chắc chắn rằng không có bản sao nơi thực hiện trước bằng cách thêm tất cả các từ điển vào một danh sách):

self.users.update({"user_id": event['userid']}, {'$addToSet': {'campaigns': UserCampaigns[i]}}) 

Nếu tôi chỉ sử dụng $ push, nó sẽ luôn tạo các phần tử trùng lặp trong 'chiến dịch' trong bộ sưu tập của người dùng. Điều này xảy ra với và không có upsert.

Vì lý do nào đó, mỗi cái không hiệu quả nhưng không bắt buộc, tôi đoán PyMongo sẽ lo cho tôi.

+1

ah, tôi đã chỉ một số người khác cho toán tử $ addToSet trước đây, nhưng tôi nghĩ cách câu hỏi được đặt thành câu trả lời liên quan đến upserts thay vì thêm vào một mảng các phần tử, đặc biệt là khi câu hỏi tóm tắt cuối cùng của bạn nói rõ: "cập nhật bộ sưu tập của tôi bằng cách sử dụng" đẩy "" khi bạn có ý nghĩa gì đó như: cập nhật mảng trong tài liệu bằng cách sử dụng tính năng đẩy mà không có phần tử trùng lặp. Tôi đã chỉnh sửa câu hỏi để phản ánh tốt hơn các yêu cầu thực tế của bạn –

+1

Có Tôi hiểu rằng các bạn có thể khó biết những gì tôi cần. Đó là lời giải thích tồi tệ của tôi về vấn đề đó là lỗi. Tôi xin lỗi, nhưng tôi đã tìm được giải pháp làm việc và lý do tại sao tôi chỉ ra rằng $ đẩy mạnh trong tiêu đề là vì tôi thực sự nghĩ đó là những gì tôi sẽ sử dụng. Dù sao, tôi đọc về $ addToSet và ngay lập tức biết đó là nhà điều hành sẽ giải quyết vấn đề của tôi. Cảm ơn sự giúp đỡ của bạn và tôi đã cập nhật chủ đề này để mọi người bối rối như tôi trong tương lai có thể được sửa chữa, như tôi đã làm. – Ms01

9

Gửi thông qua đối số thứ ba về bản cập nhật của bạn là đúng theo MongoDB DocsPyMongo Docs.

self.users.update({"user_id": event['userid']}, {'$push': {'campaigns': UserCampaign}}, True) 
+0

Tôi không thể tìm thấy tài liệu trong tài liệu, tôi có thể tìm tài liệu ở đâu? Cảm ơn câu trả lời của bạn btw! – Ms01

+0

Trong tài liệu tôi đã liên kết, chỉ cần cuộn xuống phần 'upserts'. Tôi không thể liên kết trực tiếp với nó khi họ sử dụng dấu ngoặc nhọn trong phần URI thả nổi khiến nó không hiển thị đúng liên kết. –

+0

Tôi đã thêm liên kết tới Tài liệu PyMongo trên 'cập nhật()'. Đối số thứ ba cho hàm là cờ 'upsert'. –

1

Christian có lý lẽ đúng trong câu trả lời của anh ấy, vì vậy tôi sẽ để nguyên phần đó (upvoted câu trả lời của anh ấy).

Tuy nhiên, bạn cũng hỏi về việc tránh lặp, vv

Mấu chốt ở đây là để đảm bảo rằng các tiêu chuẩn phần truy vấn cập nhật của bạn là đặc trưng cho mức độ bạn muốn. Một upsert (hoặc một bản cập nhật) chỉ tốt bằng các tiêu chí bạn đưa vào đó. Một upsert sẽ chèn một tài liệu mới nếu nó không tìm thấy tài liệu phù hợp với tiêu chí, và cập nhật sẽ chỉ thực hiện $ push (hoặc bất kỳ cập nhật nào được chỉ định) nếu tiêu chí được tìm thấy (bạn có thể cập nhật nhiều nếu nhiều hơn một doc cũng được tìm thấy).

Trong trường hợp của bạn, phần tiêu chí là:

UserCampaign = { 
     "id": campaign['id'], 
     "name": campaign['name'] 
} 

Hãy chắc chắn rằng phần này là duy nhất và bạn sẽ ổn thôi - nếu điều này có thể phù hợp với nhiều hơn một tài liệu sau đó bạn sẽ có bản sao.

+0

Cảm ơn câu trả lời của bạn, nhưng chiến dịch UserCampaign trong ví dụ của tôi không thể là duy nhất. Đó cũng là những gì tôi nghĩ. Tôi thực sự không muốn nó tạo ra một hàng mới trong bảng. Nhưng nó hy vọng sẽ không bao giờ là một chèn, vì vậy tôi đoán tôi là tốt nhưng vẫn còn một khả năng nhỏ. Có lẽ tôi nên làm một số logic python cơ bản trước khi tôi cập nhật cơ sở dữ liệu với nội dung. – Ms01

+0

Điều đó có thể là tốt nhất - tùy chọn khác sẽ là để thực thi tính duy nhất cho các tiêu chí đó, nhưng âm thanh như vậy không phải là điều bạn muốn vì các lý do khác. Bạn có thể thử thêm các bản sao để tránh mất dữ liệu nhưng đánh dấu nó như vậy (một trường bổ sung như {dupe: 1}) để bạn có thể dọn dẹp sau –

+0

Xin lỗi vì trả lời muộn. Tại sao tôi không muốn thực thi tính duy nhất là vì hàng mà tôi đang chèn vào được thu thập trước khi dữ liệu này được chèn vào. Bạn có thể xem nó như một bộ sưu tập người dùng rồi thêm một số hành động của người dùng. – Ms01

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