2016-06-12 45 views
0

我想在整个集合中的每个文档的某个现有属性上调用自定义python函数将结果作为新的键值对存储在相同)文件。我可否知道是否有办法做到这一点(因为每次通话都是独立的)?在集合中的每个文档上调用自定义python函数Mongo DB

我注意到cursor.forEach,但不能这样做只是有效地使用python?

一个简单的例子是将字符串拆分为text并存储no。的词作为一个新的属性。

def split_count(text): 
    # some complex preprocessing... 

    return len(text.split()) 

# Need something like this... 
db.collection.update_many({}, {'$set': {"split": split_count('$text') }}, upsert=True) 

但好像基于同一文档的其它属性的值在文档中设置一个新的属性是not possible这样呢。这篇文章很旧,但问题似乎仍然存在。

+0

你可以发布一些你想做的代码示例吗? –

+0

我的答案是否解决了这个问题? –

+0

@SteveRossiter呃..是和否。它解决了当前的任务(分割文本),但我也想调用_any_ python函数,这使得我很难仅使用_JS_方法。也做它_JS_弄乱了我的一些属性值。请参阅下面的答案。 :) – Kevad

回答

1

我找到了一种方法来调用在PyMongo使用parallel_scan收集任何自定义Python函数。

def process_text(cursor): 
    for row in cursor.batch_size(200): 
     # Any complex preprocessing here... 
     split_text = row['text'].split() 

     db.collection.update_one({'_id': row['_id']}, 
           {'$set': {'split_text': split_text, 
              'num_words': len(split_text) }}, 
           upsert=True) 


def preprocess(num_threads=4): 

    # Get up to max 'num_threads' cursors. 
    cursors = db.collection.parallel_scan(num_threads) 
    threads = [threading.Thread(target=process_text, args=(cursor,)) for cursor in cursors] 

    for thread in threads: 
     thread.start() 

    for thread in threads: 
     thread.join() 

这是不是真的快于cursor.forEach(但不是慢要么),但它可以帮助我执行任意复杂的Python代码,结果从内Python本身保存。

另外,如果我有一个ints在其中一个属性的数组,做cursor.forEach将它们转换为我不想要的floats。所以我更喜欢这种方式。

但是我会很高兴知道是否有更好的方法比这个:)

+0

因为Python不支持真正的并行性,所以它只能和cursor.forEach一样快,并且在通常情况下应该更慢。 –

0

在python中做这种事情是非常不可能的。这是因为文档必须往返并通过客户端机器上的python函数。

在您的示例代码中,您将函数的结果传递给mongodb update查询,这不起作用。你不能在db服务器上的MongoDB查询中运行任何python代码。

由于answer to you linked question暗示,这种类型的行为必须在mongo shell中执行。 e.g:

db.collection.find().snapshot().forEach(
    function (elem) { 
     splitLength = elem.text.split(" ").length 
     db.collection.update(

      { 
       _id: elem._id 
      }, 
      { 
       $set: { 
        split: splitLength 
       } 
      } 
     ); 
    } 
);