Luigi的MongoDB

时间:2018-01-11 15:16:02

标签: luigi

我正在尝试用luigi构建一个管道。首先从API获取数据,转换然后将其保存到mongo db。我还是luigi的新手,我的问题是如何实现output()函数,该函数指定mongo db的输出。我如何为后续任务创建require()函数?

第一个,我试图尝试演示here,但它使用的是MySql而不是mongodb。所以我试过

from luigi.contrib.mongodb import MongoTarget
from pymongo import MongoClient

def output(self):
    # connect to db
    connection = MongoClient(self.host, self.port)
    db_client = connection[self.db_name]
    collection_name = 'myCollection'

    return MongoTarget(db_client, '_id', collection_name)

但它给了我这样的错误:

TypeError: Can't instantiate abstract class MongoTarget with abstract methods exists

快速搜索错误似乎是由pyMongo引起的,但该解决方案仍无法解决问题。

对于要求部分,我不知道如何处理它,我想检查记录是否存在alraedy所以我不重复它们。但是我的API数据没有唯一的索引,所以我想我必须以某种方式扫描所有记录以确保没有重复。

关于在luigi上使用mongo没有很多文档或示例,我们非常感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

luigi.contrib.mongodb包的Luigi代码库has a test。该测试使用MongoCellTargetMongoRangeTarget。那个测试对我很有用,并且足够好用于构建。

以下代码段派生自该测试,并假设在localhost上运行一个空的MongoDB实例。

import pymongo
from luigi.contrib.mongodb import MongoRangeTarget

HOST = 'localhost'
PORT = 27017
INDEX = 'luigi_test'
COLLECTION = 'luigi_collection'

mongo_client = pymongo.MongoClient(HOST, PORT)
collection = mongo_client[INDEX][COLLECTION]

# Add sample data
test_docs = [
    {'_id': 'person_1', 'age': 11, 'experience': 10, 'content': "Lorem ipsum, dolor sit amet. Consectetur adipiscing elit."},
    {'_id': 'person_2', 'age': 12, 'experience': 22, 'content': "Sed purus nisl. Faucibus in, erat eu. Rhoncus mattis velit."},
    {'_id': 'person_3', 'age': 13, 'content': "Nulla malesuada, fringilla lorem at pellentesque."},
    {'_id': 'person_4', 'age': 14, 'content': "Curabitur condimentum. Venenatis fringilla."}
]

collection.insert_many(test_docs)

## Test reading from MongoDB via MongoRangeTarget    
test_values = [
    ('age', [], {}),
    ('age', ['unknown_person'], {}),
    ('age', ['person_1', 'person_3'], {'person_1': 11, 'person_3': 13}),
    ('age', ['person_1', 'person_3', 'person_5'], {'person_1': 11, 'person_3': 13}),
    ('experience', ['person_1', 'person_3'], {'person_1': 10}),
    ('experience', ['person_1', 'person_3', 'person_5'], {'person_1': 10}),
]

for field, ids, result in test_values:
    target = MongoRangeTarget(mongo_client, INDEX, COLLECTION, ids, field)
    assertEqual(result, target.read())

答案 1 :(得分:1)

我自己从未使用过mongodb软件包,但看起来你的第一个问题是由于滥用了MongoTarget接口。 如果你看一下这里的代码:

https://github.com/spotify/luigi/blob/master/luigi/contrib/mongodb.py#L25

您发现需要传递MongoClient的实例(connection而不是db_client)。你是对的,几乎没有任何关于非核心Luigi软件包的文档。我养成了阅读代码库的习惯,以便在使用Luigi时了解如何使用给定的包(现在我习惯使用任何库来习惯)

话虽如此,我并不认为MongoTarget是一个真正的目标;它没有实现exists方法。您应该使用模块中提供的其他目标,即MongoCellTargetMongoRangeTargetMongoCollectionTarget等 阅读他们的文档字符串,了解他们的工作!