python - 设置特定子字段的并集之间的差异

标签 python mongodb set aggregation-framework pymongo

我有一个很大的集合,可以或多或少地建模为由以下代码创建的集合:

import string
from random import randint, random, choice


documents = []


for i in range(100):
    letters =  choice(string.letters[0:15])

    documents.append({'hgvs_id': "".join([str(randint(0,9)), letters]),
                      'sample_id': "CDE",
                     'number': i*random()*50 - 30 })

    documents.append({'hgvs_id': "".join([str(randint(0,9)), letters]),
              'sample_id': 'ABC',
              'number': i*random()*50 - 30 })

    documents.append({'hgvs_id': "".join([str(randint(0,9)), letters]),
                      'sample_id': 'GEF',
                      'number': i*random()*50 - 30 })


for i in range(10):    # add some unique values for sample_id 'ABC'

    letters = choice(string.letters[0:15])
    documents.append({'hgvs_id': "55" + letters,
                      'sample_id': 'ABC',
                      'number': i*random()*50 - 30 })

collection.insert_many(documents)

我正在尝试检索具有特定 sample_id (ABC 此处),但不在包含其他两个的文档中。通常,sample_id 的数量会多于三个。

听起来很简单,但到目前为止我还没有成功。考虑到我正在使用的集合的大小(~30GB),我一直在尝试使用aggregate框架,如下所示:

sample_1 = collection.aggregate(
    [
            {'$group':
                    {
                    '_id': '$hgvs_id',

                    #'sample_id' : {"addToSet": '$hgvs_id'},
                    'matchedDocuments':
                                    {'$push':
                                            {
                                                    'id': '$_id',
                                                    'sample_name': "$sample_id",
                                                    'hgvs_ids': "$hgvs_id"
                                            }
                                    },
                    }
            },
            {'$match': {
                   "$and": [
                            {'matchedDocuments': {"$elemMatch": {'sample_name': 'ABC'}}},
                            # Some other operation????
                           ]
                     }
   } 
])  #, allowDiskUse=True) may be needed

这会返回(可以理解)所有 hgvs_idsample_id 等于 ABC。任何线索将不胜感激。

最佳答案

如果它是分组值“集合”中的唯一 sample_id,则 $size将是一个:

使用 MongoDB 3.4,您可以使用 $in组合起来:

[
  { "$group": { 
    "_id": "$hgvs_id",
    "samples": { "$addToSet": "$sample_id" }
  }},
  { "$redact": {
    "$cond": {
      "if": { 
        "$and": [
          { "$in": [ "ABC", "$samples" ] },
          { "$eq": [ { "$size": "$samples" }, 1 ] }
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
]

否则使用 $setIntersection只是语法稍长一点:

[
  { "$group": { 
    "_id": "$hgvs_id",
    "samples": { "$addToSet": "$sample_id" }
  }},
  { "$redact": {
    "$cond": {
      "if": { 
        "$and": [
          { "$eq": [ { "$size": { "$setIntersection": [ "$samples", ["ABC"] ] } }, 1 ] },
          { "$eq": [ { "$size": "$samples" }, 1 ] }
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
]

或者对于所有支持聚合的版本来说可能是最简单的形式:

  { "$group": { 
    "_id": "$hgvs_id",
    "samples": { "$addToSet": "$sample_id" }
  }},
  { "$match": {
    "$and": [{ "samples": "ABC" },{ "samples": { "$size": 1 } }]
  }}
]

同样的原则适用于任意数量的参数,因为“集合”产生的参数的大小与给定参数的大小相当,并且包含特定值。

关于python - 设置特定子字段的并集之间的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44466998/

相关文章:

python - 如何管理创建、添加数据和显示多个 matplotlib 图形?

python - 插值 4D 数据

java - 为邪恶的刽子手程序存储数据

c++ - 使用非默认比较谓词的集合容器

python - 为什么一个代码(matmul)比另一个(Python)快

python - 当多行字符串的单元测试失败时,PyCharm 显示完整差异?

java - 用于 Spring Boot 获取请求的 mongo uri

mongodb - 如何使用 Mongoose 访问预先存在的集合?

node.js - MongoDB 数据库信号量和 Node.js Process.NextTick()

ios - 如何在选择和取消选择单元格时仅保留数组中的不同元素?