热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

将数组的至少"N"个元素与条件列表相匹配

如何解决《将数组的至少"N"个元素与条件列表相匹配》经验,为你挑选了1个好方法。

我有以下场景:我的一个mongo集合包含以下格式的文档:

user: "test",
tracks: [{artist: "A", ...}, {artist: "B", ...}, ..., { artist: "N", ...}]

我想提取所有曲目,其艺术家都在给定的数组中arr.为此,我使用以下查询(工作正常).

collection.find({ tracks: { $elemMatch: { artist: { $in: arr }}}})

但是,现在我想修改查询,以便它只返回集合中的那些文档,这些文档至少让我们说arr数组中的3个不同艺术家.我怎样才能实现这一点(除了从数据库返回后过滤结果,这不是一个选项)?



1> Neil Lunn..:

你的问题对我来说有两种可能,但也许有些解释可以让你开始.

首先,我需要向你解释你误解了$elemMatch它的意图,并且在这种情况下它被误用了.

想法$elemMatch是创建一个实际应用于数组元素的"查询文档".目的是在数组中的文档上具有"多个条件",以便在成员文档中离散地匹配它,而不是在外部文档的整个数组中.即:

{
   "data": [
       { "a": 1, "b": 3 },
       { "a": 2, "b": 2 }
   ]
}

以下查询将起作用,即使该数组中没有实际的单个元素匹配,但整个文档执行:

db.collection.find({ "data.a": 1, "data.b": 2 })

但要检查实际元素是否与这两个条件匹配,这是您使用的位置$elemMatch:

db.collection.find({ "data": { "a": 1, "b": 2 } })

因此该样本中没有匹配,并且它只匹配特定数组元素具有这两个元素的位置.


现在我们已经$elemMatch解释过,这是您的简化查询:

db.collection.find({ "tracks.artist": { "$in": arr } })

更简单,它的工作原理是通过单个字段查看所有数组成员,并返回文档中的任何元素至少包含其中一个可能结果的位置.

但不是你问的问题,等你的问题.如果你仔细阅读最后一个陈述,你应该意识到这$in实际上是一个$or条件.它只是一个缩短的形式,用于询问文档中相同元素的"或".

考虑到这一点,您所要求的核心是"和"操作,其中包含所有"三个"值.假设您只是在测试中发送"三个"项目,那么您可以使用$and以下缩写形式的形式$all:

db.collection.find({ "tracks.artist": { "$all": arr } })

这只会返回具有该数组成员中的元素的文档,该元素匹配测试条件中指定的"所有"元素.这可能就是你想要的,但有一种情况当然你想指定一个说"四个或更多"艺术家的名单来测试,只想要"三个"或更少的数字,在这种情况下一个$all运营商太简洁.

但是有一种合理的方法可以解决这个问题,只需要对基本查询不可用的运算符进行更多处理,但聚合框架可以使用这些运算符:

var arr = ["A","B","C","D"];     // List for testing

db.collection.aggregate([
    // Match conditions for documents to narrow down
    { "$match": {
        "tracks.artist": { "$in": arr },
        "tracks.2": { "$exists": true }      // you would construct in code
    }},

    // Test the array conditions
    { "$project": {
        "user": 1,
        "tracks": 1,                         // any fields you want to keep
        "matched": {
            "$gte": [
                 { "$size": {
                     "$setIntersection": [
                         { "$map": {
                             "input": "$tracks",
                             "as": "t",
                             "in": { "$$t.artist" }
                         }},
                         arr
                     ]
                 }},
                 3
             ]
        }
    }},

    // Filter out anything that did not match
    { "$match": { "matched": true } }
])

第一阶段实现标准查询$match条件,以便将文档过滤到"可能"匹配条件的文档.这里的逻辑情况是$in像以前一样使用它将找到那些文档,其中"test"数组中至少有一个元素存在于文档自己的数组中的至少一个成员字段中.

下一个子句是理想情况下应该在代码中构建的,因为它与数组的"长度"有关.这里的想法是你想要至少"三个"匹配,然后你在文档中测试的数组必须至少有"三个"元素才能满足这一要求,所以检索具有"两个"或更少数组元素的文档没有意义因为他们永远不会匹配"三".

由于所有MongoDB查询基本上只是数据结构的表示,因此它非常容易构建.即,对于Javascript:

var matchCount = 3;    // how many matches we want

var match1 = { "$match": { "tracks.artist": { "$in": arr } } };

match1["$match"]["tracks."+ (matchCount-1)] = { "$exits": true };

逻辑是"点符号"形式,$exists用于测试指定索引(n-1)处元素的存在,并且数组需要至少具有该长度.

其余的缩小理想情况下使用该$setIntersection方法以返回实际数组和测试数组之间的匹配元素.由于文档中的数组与"测试数组"的结构不匹配,因此需要通过$map设置转换的操作进行转换,该操作仅从每个数组元素返回"artist"字段.

当制作这两个阵列的"交叉点"时,最终测试$size所得到的常见元素列表,其中应用测试以查看这些元素中的"至少三个"被发现是共同的.

最后,你只是"过滤掉"任何使用$match条件不真实的东西.


理想情况下,您使用MongoDB 2.6或更高版本以使这些运算符可用.对于早期版本的2.2.x和2.4.x,它仍然可以,但只需要更多的工作和处理开销:

db.collection.aggregate([
    // Match conditions for documents to narrow down
    { "$match": {
        "tracks.artist": { "$in": arr },
        "tracks.2": { "$exists": true }      // you would construct in code
    }},

    // Unwind the document array
    { "$unwind": "$tracks" },

    // Filter the content
    { "$match": { "tracks.artist": { "$in": arr } }},

    // Group for distinct values
    { "$group": {
        "_id": { 
           "_id": "$_id",
           "artist": "$tracks.artist"
        }
    }},

    // Make arrays with length
    { "$group": {
        "_id": "$_id._id",
        "artist": { "$push": "$_id.artist" },
        "length": { "$sum": 1 }
    }},

    // Filter out the sizes
    { "$match": { "length": { "$gte": 3 } }}
])


推荐阅读
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文介绍了Perl的测试框架Test::Base,它是一个数据驱动的测试框架,可以自动进行单元测试,省去手工编写测试程序的麻烦。与Test::More完全兼容,使用方法简单。以plural函数为例,展示了Test::Base的使用方法。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 也就是|小窗_卷积的特征提取与参数计算
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了卷积的特征提取与参数计算相关的知识,希望对你有一定的参考价值。Dense和Conv2D根本区别在于,Den ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 判断数组是否全为0_连续子数组的最大和的解题思路及代码方法一_动态规划
    本文介绍了判断数组是否全为0以及求解连续子数组的最大和的解题思路及代码方法一,即动态规划。通过动态规划的方法,可以找出连续子数组的最大和,具体思路是尽量选择正数的部分,遇到负数则不选择进去,遇到正数则保留并继续考察。本文给出了状态定义和状态转移方程,并提供了具体的代码实现。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • Explain如何助力SQL语句的优化及其分析方法
    本文介绍了Explain如何助力SQL语句的优化以及分析方法。Explain是一个数据库SQL语句的模拟器,通过对SQL语句的模拟返回一个性能分析表,从而帮助工程师了解程序运行缓慢的原因。文章还介绍了Explain运行方法以及如何分析Explain表格中各个字段的含义。MySQL 5.5开始支持Explain功能,但仅限于select语句,而MySQL 5.7逐渐支持对update、delete和insert语句的模拟和分析。 ... [详细]
  • 大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记
    本文介绍了大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记,包括outputFormat接口实现类、自定义outputFormat步骤和案例。案例中将包含nty的日志输出到nty.log文件,其他日志输出到other.log文件。同时提供了一些相关网址供参考。 ... [详细]
  • 本文介绍了如何在Jquery中通过元素的样式值获取元素,并将其赋值给一个变量。提供了5种解决方案供参考。 ... [详细]
author-avatar
tuitu
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有