我在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
元组列表。我可以舍入最接近的整数百分比。这似乎需要在每次我插入某项内容或插入所有内容之后,在某个perc_identity
中的每个元组中检查是否存在该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
阈值构建查询的最佳方法。
发布于 2016-02-07 06:49:52
这不是一个容易回答的问题!然而,指导原则应该是根据您打算使用数据的方式来决定。在本例中,您提到了两个查询:
perc_identity > 95
抓取所有对(当然,你可能还计划进行其他一些常见的分析-这将有助于把它们说出来。)
基于此,我鼓励你们采取一种非正规化的方法,就像你们在第三种选择中所讨论的那样。它确实有一些缺点,主要是在insert方面,您似乎已经注意到了这一点,但它使第一类查询非常容易:
db.hits.find({perc_identity: {$gt: 95}})
使用任何其他方法,...whereas都需要迭代其他文档中的所有键。例如,使用第一种方法,您需要检索每个基因的hits
子文档,遍历这些子文档的键,并将大于95的文档添加到列表中。这需要用mongodb/pymongo来完成。
另一个查询比使用方法1和2要复杂得多,但并不是很复杂:
db.hits.find({$or: [{pair1: <your gene>}, {pair2: <your gene>}]})
因此,以更多的插入逻辑为代价,您提到的两个查询用例变得非常简单,可以由数据库服务器本身轻松地处理。如果你有第三种方法很难实现的其他通用用例,那就值得重新审视它--但就目前的情况而言,这是我的选择。
两个注意事项:首先,MongoDB的文档中有可能值得阅读的关于数据建模的一些好建议。其次,尽管我非常喜欢MongoDB,但考虑到我对您的问题域知之甚少,这可能是关系数据库可能更适合的一种情况。
https://stackoverflow.com/questions/35243278
复制相似问题