2012-04-04 31 views
12

Tôi có một truy vấn, trong đó chọn tài liệu cần xóa. Ngay bây giờ, tôi xóa chúng theo cách thủ công, như thế này (sử dụng python):Làm thế nào để xóa tài liệu theo truy vấn một cách hiệu quả trong mongo?

for id in mycoll.find(query, fields={}): 
    mycoll.remove(id) 

Điều này dường như không hiệu quả lắm. Có cách nào tốt hơn?

EDIT

OK, tôi nợ một lời xin lỗi cho quên đề cập đến các chi tiết truy vấn, bởi vì nó quan trọng. Đây là mã python hoàn chỉnh:

def reduce_duplicates(mydb, max_group_size): 
    # 1. Count the group sizes 
    res = mydb.static.map_reduce(jstrMeasureGroupMap, jstrMeasureGroupReduce, 'filter_scratch', full_response = True) 
    # 2. For each entry from the filter scratch collection having count > max_group_size 
    deleteFindArgs = {'fields': {}, 'sort': [('test_date', ASCENDING)]} 
    for entry in mydb.filter_scratch.find({'value': {'$gt': max_group_size}}): 
    key = entry['_id'] 
    group_size = int(entry['value']) 
    # 2b. query the original collection by the entry key, order it by test_date ascending, limit to the group size minus max_group_size. 
    for id in mydb.static.find(key, limit = group_size - max_group_size, **deleteFindArgs): 
     mydb.static.remove(id) 
    return res['counts']['input'] 

Vì vậy, nó sẽ làm gì? Nó giảm số lượng khóa trùng lặp xuống tối đa max_group_size cho mỗi giá trị khóa, chỉ để lại các bản ghi mới nhất. Nó hoạt động như sau:

  1. MR dữ liệu tới (key, count) cặp.
  2. lặp qua tất cả các cặp với count > max_group_size
  3. Truy vấn dữ liệu bằng cách key, trong khi sắp xếp nó tăng dần bởi dấu thời gian (người đầu tiên lâu đời nhất) và hạn chế kết quả cho count - max_group_size hồ sơ lâu đời nhất
  4. Xóa mỗi kỷ lục được tìm thấy.

Như bạn có thể thấy, điều này hoàn thành nhiệm vụ giảm số bản sao xuống tối đa N bản ghi mới nhất. Vì vậy, hai bước cuối cùng là foreach-found-remove và đây là chi tiết quan trọng của câu hỏi của tôi, điều đó thay đổi mọi thứ và tôi phải cụ thể hơn về nó - xin lỗi.

Bây giờ, về lệnh xóa bộ sưu tập. Nó chấp nhận truy vấn, nhưng tôi bao gồm phân loại và hạn chế. Tôi có thể làm điều đó với loại bỏ? Vâng, tôi đã thử:

mydb.static.find(key, limit = group_size - max_group_size, sort=[('test_date', ASCENDING)]) 

Nỗ lực này thất bại thảm hại. Hơn nữa, nó có vẻ như vít mongo.Observe:

C:\dev\poc\SDR>python FilterOoklaData.py 
bad offset:0 accessing file: /data/db/ookla.0 - consider repairing database 

Không cần phải nói, cách tiếp cận tìm kiếm-tìm-loại bỏ hoạt động và mang lại kết quả mong đợi.

Bây giờ, tôi hy vọng tôi đã cung cấp đủ ngữ cảnh và (hy vọng) đã khôi phục danh dự bị mất của tôi.

Trả lời

9

Bạn có thể loại bỏ nó trực tiếp sử dụng ngôn ngữ MongoDB kịch bản:

db.mycoll.remove({_id:'your_id_here'}); 
+0

Tôi đã chỉnh sửa bài viết của tôi. – mark

28

Bạn có thể sử dụng một truy vấn để loại bỏ tất cả các văn bản phù hợp với

var query = {name: 'John'}; 
db.collection.remove(query); 

Hãy cảnh giác, tuy nhiên, nếu số tài liệu phù hợp là rất cao , cơ sở dữ liệu của bạn có thể ít phản hồi hơn. Nó thường được khuyên để xóa tài liệu trong các đoạn nhỏ hơn.

Giả sử bạn có 100 nghìn tài liệu cần xóa khỏi bộ sưu tập. Nó là tốt hơn để thực hiện 100 truy vấn xóa 1k tài liệu mỗi truy vấn 1 xóa tất cả các tài liệu 100k.

+0

Tôi đã chỉnh sửa bài đăng của mình. – mark

+0

'Giả sử bạn có 100 nghìn tài liệu cần xóa khỏi bộ sưu tập. Tốt hơn là thực thi 100 truy vấn xóa 1k tài liệu trên mỗi 1 truy vấn xóa tất cả tài liệu 100k.' Làm cách nào bạn có thể đạt được điều này? – Ezequiel

+1

@Ezequiel: người ta có thể tìm nạp id của tất cả các tài liệu cần xóa, sau đó chia chúng thành các lô 1000 và gửi một số lệnh xóa với toán tử '$ in'. –

0

Chạy truy vấn này trong cmd

db.users.remove ({ "_id": ObjectId ("5a5f1c472ce1070e11fde4af")});

Nếu bạn đang sử dụng Node.js viết mã này

User.remove({ _id: req.body.id },, function(err){...}); 
Các vấn đề liên quan