代表Mongo DB中的互惠关系

时间:2016-02-06 16:19:32

标签: python mongodb nosql

我在mongoDB中有一组东西(基因)。我正在进行分析,以了解每个基因与其他基因的相似程度,并且我希望将这些信息存储在数据库中。我目前在数据库中为每个基因提供了不同的文件,其中包含基因来自何种物种和DNA序列等信息。当然,每个人都有一个唯一的标识符_id

当我进行分析时,我将获得有关相似基因百分比(他们的perc_identity)的信息。通常,分析可以返回的下限约为70%,因此每个基因不一定有一个数字,但每个关系都是互逆的(例如perc_identity(A:B) == 90然后perc_identity(B:A) == 90)。

我的问题是存储这些关系的最佳数据模型是什么,以便我可以检索它们以进行进一步分析?换句话说,有时我会想要抓住perc_identity > 95所有的对。其他时候,我想要获得特定基因的所有匹配。如果它很重要,获得perc_identity的初始分析只需要进行一次并且已经花了相当长的时间,因此插入的性能比检索更重要,以便以后分析。

我有一些想法(如果重要的话,我在python中使用mongoDB):

1)在每个基因的文档中,有一个子文档,其中包含所有匹配的_id及其perc_identity。例如:

{
    _id: geneA,
    dna_seq: 'AACTG...',
    species: 'Homo sapiens',
    hits:{
        geneA: 100,
        geneB: 92,
        geneC: 70,
    }
},
{
    _id: geneB,
    dna_seq: 'AATTG...',
    species: 'Pan troglodytes',
    hits:{
        geneA: 92,
        geneB: 100,
    }
},
{
    _id: geneC,
    dna_seq: 'ATGGC...',
    species: 'Homo erectus',
    hits:{
        geneA: 70
        geneC: 100
    }
}

这显然会导致一些数据重复,但这与数据从初始分析中吐出的方式最接近。大多数时候,我不会关心gene文档中的大多数其他数据,所以我不清楚它是否会降低速度以使信息嵌套在其中。我还不清楚是否有一种有效的查询方法,例如,所有perc_identity > 90。每次我想进行分析时,我都会检索到需要的数据量的两倍。

2)有一个单独的文档,其中只包含基因_id及其所有命中。例如:

{
    _id: 'hits',
    geneA: {
        geneA: 100
        geneB: 92
        geneC: 70
    },
    geneB: {
        geneA: 92
        geneB: 100
    },
    # etc
}

这样做的好处是我根本不必弄乱基因文件。如果有任何不同,我也可以有一个不同的hits集合。另一个好处是会有~50k的基因记录,但只有大约1-2%的基因记录会有任何命中,因此查询不会打扰检查大多数文档。否则,这似乎与(1)对我非常相似。

3)某种方式没有冗余。我无法想出这样做的好方法。我想到的坏方法是让perc_identity成为关键,然后列出_id元组。我可以舍入到最接近的整数百分比。这似乎需要在每次插入内容时检查某个_id内每个元组中是否存在perc_identity,或者插入所有内容然后再折叠该集合。在这种情况下,检索特定_id的所有匹配似乎会非常低效。

或者,因为订单并不重要:

{
    _id: ?
    type: 'hit'
    pair1: geneA
    pair2: geneB
    perc_identity: 92
},
{
    _id: ??
    type:'hit'
    pair1: geneC
    pair2: geneA
    perc_identity: 70
},
# etc

对这些策略之一的任何批评,或对其他表达方式的建议都将非常感激。如果我有其他信息我应该提供或者我是否可以澄清任何内容,请告诉我。如果(1)或(2)看起来是好策略,我想我唯一的问题是基于某个perc_identity阈值构建查询的最佳方法。

1 个答案:

答案 0 :(得分:1)

这绝不是一个容易回答的问题!但是,指导原则应该是根据您打算使用数据的方式来决定。在这种情况下,您提到了两个问题:

  1. 使用perc_identity > 95
  2. 抓取所有对
  3. 获取一个基因的所有匹配
  4. (当然,您可能会进行其他常见的分析 - 这有助于拼出它们。)

    基于此,我建议您采用非正规化方法,就像您在第三种方案中讨论的方法一样。它确实有一些缺点,主要是在插入,你似乎知道,但它使第一种类型的查询非常容易:

    db.hits.find({perc_identity: {$gt: 95}})
    

    ...而对于任何其他方法,您需要迭代其他文档中的所有键。例如,使用第一种方法,您需要检索每个基因的hits子文档,迭代这些子文档的键,并将那些大于95的列表添加到列表中。这需要完成出自mongodb / pymongo。

    另一个查询比方法1和方法2更复杂,但不是很多:

    db.hits.find({$or: [{pair1: <your gene>}, {pair2: <your gene>}]})
    

    因此,以插入的更多逻辑为代价,您提到的两个查询案例变得非常简单,并且可以由数据库服务器本身轻松处理。如果你有其他常见的用例很难通过你的第三种方法实现,那么值得重新审视它 - 但就目前而言,那是我会选择的。

    两个注意事项:首先,MongoDB的文档有some good advice on data modeling,值得一读。其次,就像我喜欢MongoDB一样,鉴于我对你的问题域知之甚少,这可能是关系数据库可能更适合的一种情况。