首页 文章

N1QL嵌套json,查询数组内对象内的字段

提问于
浏览
1

我的Couchbase集群中有json文档,看起来像这样

{
    "giata_properties": {
      "propertyCodes": {
        "provider": [
          {
            "code": [
              {
                "value": [
                  {
                    "name": "Country Code",
                    "value": "EG"
                  },
                  {
                    "name": "City Code",
                    "value": "HRG"
                  },
                  {
                    "name": "Hotel Code",
                    "value": "91U"
                  }
                ]
              }
            ],
            "providerCode": "gta",
            "providerType": "gds"
          },
          {
            "code": [
              {
                "value": [
                  {
                    "value": "071801"
                  }
                ]
              },
              {
                "value": [
                  {
                    "value": "766344"
                  }
                ]
              }
            ],
            "providerCode": "restel",
            "providerType": "gds"
          },
          {
            "code": [
              {
                "value": [
                  {
                    "value": "HRG03Z"
                  }
                ]
              },
              {
                "value": [
                  {
                    "value": "HRG04Z"
                  }
                ]
              }
            ],
            "providerCode": "5VF",
            "providerType": "tourOperator"
          }
        ]
      }
    }
  }

我正在尝试创建一个基于 giata_properties.propertyCodes.provider.code.value.value 和特定 providerType 的值来获取单个文档的查询 .

所以例如,我的输入是 071801restel ,我想要一个查询,它将获取我粘贴在上面的文档(因为它包含这些值) .

我对N1QL很新,所以到目前为止我尝试的是(没有providerType输入)

SELECT * FROM giata_properties AS gp 
WHERE ANY `field` IN `gp.propertyCodes.provider.code.value` SATISFIES `field.value` = '071801' END;

这会返回一个空结果集 . 我可能错误地做了所有这些 .

edit1:

根据杰拉德斯的回答,我能够通过2个不同的查询实现我的目标

1(更一般) ~2m50.9903732s

SELECT * FROM giata_properties AS gp WHERE ANY v WITHIN gp SATISFIES v.`value` = '071801' END;

2(更具体) ~2m31.3660388s

SELECT * FROM giata_properties AS gp WHERE ANY v WITHIN gp.propertyCodes.provider[*].code SATISFIES v.`value` = '071801' END;

Bucket有大约550K文件 . 目前没有索引,但主要是 .

Question part 2

当我执行上述任一查询时,我会很快将结果流式传输到我的shell,然后我花费剩余的查询时间等待引擎完成迭代所有文档 . 我确信我将来只会得到未来查询的1个结果所以我认为我可以使用LIMIT 1,所以引擎停止搜索第一个结果,我尝试了类似的东西

SELECT * FROM giata_properties AS gp WHERE ANY v WITHIN gp SATISFIES v.`value` = '071801' END LIMIT 1;

但这没有任何区别,我得到一个写入我的shell的文档,然后一直等待查询完成 . 如何正确配置?

edit2:

我已升级到最新的企业 4.5.1-2844 ,我只在 giata_properties 存储桶上创建了主索引,当我执行查询以及LIMIT 1关键字时,它仍然需要相同的时间,它不会更快地停止 .

我也试过创建你建议的数组索引,但查询没有使用索引,它一直坚持使用 #primary 索引(即使我使用USE INDEX子句) .

我尝试从你建议的索引中删除SELF,并且花了更长的时间来构建,现在查询可以使用这个新索引,但我老实说不确定我在这里做什么 .

所以3个问题:

1)为什么LIMIT 1使用主索引不会使查询在第一次结果停止?

2)您建议使用和不使用SELF的索引之间有什么区别?我试图寻找 SELF 关键字文档,但我找不到任何东西 .

这是两个索引在Web ui中的外观

索引1(您的原始建议) - 不工作

CREATE INDEX `gp_idx1` ON `giata_properties`((distinct (array (`v`.`value`) for `v` within (array_star((((self.`giata_properties`).`propertyCodes`).`provider`)).`code`) end)))

索引2(没有 SELF

CREATE INDEX `gp_idx2` ON `giata_properties`((distinct (array (`v`.`value`) for `v` within (array_star(((self.`propertyCodes`).`provider`)).`code`) end)))

3)特定 giata_properties.propertyCodes.provider.code.value.value 和特定 providerCode 的查询是什么?我设法分开做了两件事,但我没有成功合并它们 .

亲爱的,谢谢你的帮助

1 回答

  • 2

    这是一个没有 providerType 的查询 .

    EXPLAIN SELECT *
    FROM giata_properties AS gp
    WHERE ANY v WITHIN gp.giata_properties.propertyCodes.provider[*].code SATISFIES v.`value` = '071801' END;
    

    您也可以在Couchbase 4.5.0及更高版本中对此进行索引 .

    CREATE INDEX idx1 ON giata_properties( DISTINCT ARRAY v.`value` FOR v WITHIN SELF.giata_properties.propertyCodes.provider[*].code END );
    

    Edit to answer question edits

    性能已在4.5.x中得到解决 . 您应该在Couchbase 4.5.1上尝试以下操作并在此处发布执行时间 .

    • 测试4.5.1 .

    • 创建索引 .

    • 使用LIMIT . 在4.5.1中,限制被下推到索引 .

相关问题