如何使用pymongo在数组中搜索值

时间:2014-11-23 21:07:08

标签: python mongodb pymongo

我正在编写一个Web Crawler,现在它已经工作了,我想制作一个get_inverted_index函数。 因此,我有两个集合:词典和文档。在文档词典的每个文档中,我有一个名为words的数组,其中包含每个文档(页面)中每个单词的id和字体大小。我的下一步是迭代单词并查找具有每个特定单词的文档,但我看不到如何为此请求编写查询。我尝试了以下代码段:

k = {}
for word in self.lexicon.find():
    s = set()
    for page in self.documents.find({'words' : {'$in' : word['_id'}}):

但是这个查询无法正常工作。 例如,我的词典集合中的一个条目:

{
    "_id": {
        "$oid": "54723c55b59c44a167ed3424"
    },
    "word": "google"
}

我的文件集中的一个例子:

{
    "_id": {
        "$oid": "54723c54b59c44a167ed3423"
    },
    "url": "http://www.google.com",
    "words": [
        [
            {
                "$oid": "54723c55b59c44a167ed3424"
            },
            7
        ],
        [
            {
                "$oid": "54723c55b59c44a167ed3425"
            },
            2
        ],
        [
            {
                "$oid": "54723c55b59c44a167ed3428"
            },
            0
        ],
        [
            {
                "$oid": "54723c55b59c44a167ed342b"
            },
            0
        ],
        [
            {
                "$oid": "54723c56b59c44a167ed342e"
            },
            0
        ],
        [
            {
                "$oid": "54723c5eb59c44a167ed3477"
            },
            0
        ]
    ]
}

@Edit

我也尝试使用正则表达式,但没有成功:(用于测试表达式)

for page in documents.find({'words' : [ObjectId('547244abb59c44a167ed4a84'), {"$regex": "*"}]}):
    print page

另外

for page in documents.find({'words' : [{'$in' : ObjectId('547244abb59c44a167ed4a84')}, {'$regex': '*'}]}):

    print page

2 个答案:

答案 0 :(得分:1)

对于文档集合来说,这是一个非常不幸的架构选择。

你说你有一个名为words的数组,其中包含每个文档中每个单词的id和字体大小。不幸的是,你有这个id和字体大小作为另一个数组。有意义的是将id和字体大小作为子文档中的命名字段。换句话说,你需要一个字典列表,而不是列表列表。

{  "_id":   <id here>,
   "url": "http://www.google.com",
   "words": [
       { "id":<id>, "fs":7 },
       { "id":<id>, "fs":2 }
   ]
}

这样可以通过documents.find({"words.id":<id>})查询进行查询。此外,如果您碰巧想要跟踪每个单词的其他内容,那么第二个数字意味着什么也不会是个谜。

虽然你可以设法做一个恰好返回你想要的模式的查询,但它实际上并不适合它所描述的内容。但是,如果 决定继续使用当前结构,则查询它的正确方法是

documents.find({'words':{'$elemMatch':{'0':word['_id']}}})

而不是使用double $ elemMatch,此语法专门查找其第一个元素与所讨论的_id匹配的数组元素。

答案 1 :(得分:0)

看起来您需要在更深层次上搜索文档集合。

截至目前,您正在搜索元素

{
    "$oid": "54723c55b59c44a167ed3424"
}

文档集合的$ in运算符将其与列表元素进行比较,例如:

[
    {
        "$oid": "54723c55b59c44a167ed3424"
    },
    7
]

这显然不一样了。不幸的是我没有mongodb来测试任何东西,但也许这个技巧可以帮助你改善你的查询。

编辑: 找到关于类似问题的较早问题here,这可能会有所帮助。根据那篇文章,类似下面的作品:

for page in documents.find({'words':{$elemMatch:{$elemMatch:{$in:[word['_id']]}}}})