繁体   English   中英

在mongodb中使用索引搜索值

Search values using Index in mongodb

提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供   中文繁体   英文版本   中英对照 版本,有任何建议请联系yoyou2525@163.com。

我是Mongodb的新手,希望对mongo collection中的字段进行搜索。

我的测试集合具有以下结构:-

{
  'key': <unique key>,
  'val_arr': [
               ['laptop', 'macbook pro', '16gb', 'i9', 'spacegrey'],
               ['cellphone', 'iPhone', '4gb', 't2', 'rose gold'],
               ['laptop', 'macbook air', '8gb', 'i5', 'black'],
               ['router', 'huawei', '10x10', 'white'],
               ['laptop', 'macbook', '8gb', 'i5', 'silve'],
}

我希望根据索引号和值找到它们,即找到其中val_arr中的第一个元素是laptop而第三个元素的值为8gb的条目。

我尝试查看mongodb中的复合索引,但是它们的索引限制为32个键。 对此方向的任何帮助将不胜感激。

1 个回复

这里的索引限制,但实际上并不重要。 在您的情况下,您实际上说的是'key': <unique key> 因此,如果这确实是“唯一的”,那么它是集合中唯一需要索引的东西,只要您实际上在每个查询中都包含"key" ,因为这将决定您选择一个文档。

除非您实际上打算直接在文档中搜索那些元素,否则在文档“内部”的数组上的索引并不重要。 可能是这种情况,但这实际上与按编号的索引位置匹配您的值没有关系:

db.collection.find(
  {
    "val_arr": {
      "$elemMatch": { "0": "laptop", "2": "8gb" }
    }
  },
  {  "val_arr.$": 1 }
)

哪个会返回:

{
    "val_arr" : [
        [
            "laptop",
            "macbook air",
            "8gb",
            "i5",
            "black"
        ]
    ]
}

$elemMatch允许您在同一数组元素上表达“多个条件”。 这是标准点表示法形式所需要的,因为否则条件只是寻找与索引值匹配的“任何”数组成员。 例如:

db.collection.find({ "val_arr.0": "laptop", "val_arr.2": "4gb" })

尽管单个“行”上不存在“组合”,但实际上与给定文档匹配,但是两个值实际上作为一个整体存在于数组中。 但是只是在不同的成员中。 将这些相同的值与$elemMatch可确保该对在同一元素上匹配。

请注意上面示例中的{ "val_arr.$": 1 } ,它是“单个”匹配元素的投影。 这是可选的,但这只是在谈论识别匹配项。

使用.find()可以做到很多,并且是位置运算符的限制,因为它只能识别一个匹配元素。 对于“多个匹配项”执行此操作的方法是将aggregate()$filter

db.collection.aggregate([
  { "$match": {
    "val_arr": {
      "$elemMatch": { "0": "laptop", "2": "8gb" }
    }
  }},
  { "$addFields": {
    "val_arr": {
      "$filter": {
        "input": "$val_arr",
        "cond": {
          "$and": [
            { "$eq": [ { "$arrayElemAt": [ "$$this", 0 ] }, "laptop" ] },
            { "$eq": [ { "$arrayElemAt": [ "$$this", 2 ] }, "8gb" ] }
          ]
        }
      }
    }
  }}
])

哪个返回:

{
        "key" : "k",
        "val_arr" : [
                [
                        "laptop",
                        "macbook air",
                        "8gb",
                        "i5",
                        "black"
                ],
                [
                        "laptop",
                        "macbook",
                        "8gb",
                        "i5",
                        "silve"
                ]
        ]
}

实际选择匹配文档的初始查询条件进入$match并且与前面显示的查询条件完全相同。 $filter用于仅获取实际上与条件匹配的元素。 这些条件在逻辑表达式内对$arrayElemAt进行了类似的用法,即如何将"0""2"的索引值应用于查询条件本身。

与标准查询引擎功能相比,使用任何聚合表达式都会产生额外的费用。 因此,始终最好在潜水和使用陈述之前考虑是否确实需要它。 只要执行常规查询表达式,总会更好。

改变结构

当然,虽然可以在数组的索引位置上进行匹配,但这些方法实际上都无法帮助创建可用于加速查询的“索引”。

最好的方法是实际使用有意义的属性名称而不是普通数组:

{
  'key': "k",
  'val_arr': [
    { 
      'type': 'laptop',
      'name': 'macbook pro',
      'memory': '16gb',
      'processor': 'i9',
      'color': 'spacegrey'
    },
    {
      'type': 'cellphone',
      'name': 'iPhone',
      'memory': '4gb',
      'processor': 't2',
      'color': 'rose gold'
    },
    {
      'type': 'laptop',
      'name': 'macbook air',
      'memory': '8gb',
      'processor': 'i5',
      'color': 'black'
    },
    { 
      'type':'router',
      'name': 'huawei',
      'size': '10x10',
      'color': 'white'
    },
    { 
      'type': 'laptop',
      'name': 'macbook',
      'memory': '8gb',
      'processor': 'i5',
      'color': 'silve'
    }
  ]
}

这确实允许您“在合理范围内”将数组中属性名称的路径作为复合索引的一部分包括在内。 例如:

db.collection.createIndex({ "val_arr.type": 1, "val_arr.memory": 1 })

然后,实际上发出查询在代码中看起来比02隐含值更具描述性:

db.collection.aggregate([
  { "$match": {
    "val_arr": {
      "$elemMatch": { "type": "laptop", "memory": "8gb" }
    }
  }},
  { "$addFields": {
    "val_arr": {
      "$filter": {
        "input": "$val_arr",
        "cond": {
          "$and": [
            { "$eq": [ "$$this.type", "laptop" ] },
            { "$eq": [ "$$this.memory", "8gb" ] }
          ]
        }
      }
    }
  }}
])

预期结果,更有意义:

{
        "key" : "k",
        "val_arr" : [
                {
                        "type" : "laptop",
                        "name" : "macbook air",
                        "memory" : "8gb",
                        "processor" : "i5",
                        "color" : "black"
                },
                {
                        "type" : "laptop",
                        "name" : "macbook",
                        "memory" : "8gb",
                        "processor" : "i5",
                        "color" : "silve"
                }
        ]
}

多数人到达问题中的结构的常见原因通常是因为他们认为自己在节省空间。 并非完全不是事实 ,而且对于存储引擎的大多数现代优化,MongoDB所使用的方法与预期的任何小收益基本上无关。

因此,为了“清晰”起见,并且为了实际支持对“数组”中的数据进行索引,您实际上应该更改结构并在此处使用命名属性。

再一次,如果您对数据的整个使用模式没有在查询中使用文档的key属性,那么最好将这些条目存储为单独的文档,而不是放在一个数组中。 这也使获得结果的效率更高。

因此,要分解所有这些选项,实际上是:

  • 实际上,您始终key作为查询的一部分,因此,除了该属性外,其他任何地方的索引都无关紧要。
  • 您更改为使用命名属性作为数组成员上的值,从而使您可以为这些属性建立索引,而无需达到“多键限制”
  • 您决定始终不使用key访问此数据,因此只需将所有数组数据作为具有适当命名属性的单独文档写入集合中即可。

从本质上讲,最适合您需求的解决方案之一就是使您能够有效处理所拥有数据类型的解决方案。

注意:与主题无关(实际上可能没有关于存储大小的注释),但是通常建议将具有固有数字值的内容(例如memory"8gb"类型的数据)实际表示为数字,而不是比“字符串”。

简单的推理是,尽管您可以查询"8gb"相等,但这对“ 4至12 GB之间”的范围没有帮助。

因此,使用88000类的数值通常更有意义。 请注意,数字值实际上将对存储产生影响,因为它们通常会比字符串占用更少的空间。 考虑到省略属性名可能一直在尝试减少存储量,但是什么也不做,这确实显示了可以减小存储量的实际区域。

1 MongoDB全文搜索不使用索引

我们使用mongoDB全文搜索在数据库中查找产品。 不幸的是,这是令人难以置信的缓慢。 该集合包含89.114.052文档,我怀疑没有使用全文本索引。 使用explain()执行搜索时,nscannedObjects返回133212。如果使用索引,这不应该为0吗? 我的索引: ...

3 在 Mongoose Mongodb 上使用 INDEX 搜索数据

我正在使用 mongoose + nodejs 在 mongodb 数据库中进行查询。 但是我想使用索引进行搜索,例如 第 2.3 章 =“你好世界” 所以我想拉入数据库 并返回“你好世界” 是否可以使用 .find() 并使用索引进行搜索,类似的数组操作??? 我有一个解决方案,使用 ...

6 使用DropWizard和MongoDB在多个值中搜索关键字

我想在所有MongoDB文档的多个值中搜索一个字符串,然后返回匹配的文档。 这就是我试图用一把钥匙做的事情 如何更改它以搜索所有键/值中的值? 我在客户集合的每个文档中都有firstName, lastName, email, phoneNumber 。 有什么建议吗? ...

7 MongoDB索引搜索

我正在执行以下查询 而且我的文档集合里面有下面的架构 我有以下索引 当我用explain()执行提到的find()时,它正在执行集合扫描而不是索引扫描。 请为上述find()建议其他合适的索引吗? ...

9 mongodb图集搜索索引

我想创建返回所有对象的索引,其中用户名包含我试过这个代码的术语: 它工作得很好,但由于大量数据而滞后,我用 mongodb atlas 尝试了这段代码 除非搜索的词与## 标题## 完整用户名相同,否则此代码不会返回结果 ...

10 使用具有多个值的INDEX / MATCH作为关键字搜索

我正在尝试让I4根据G列上的文本来检索子主题。我使用了= INDEX($ B $ 2:$ B $ 4,MATCH(TRUE,ISNUMBER(SEARCH($ C $ 2:$ C $ 4,$ G4)),0))使用1个关键字检索H列。 有什么解决方法吗? 我已经尝试过使用图中的使用公式进行尝试,但 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2022 STACKOOM.COM