如何在 Cloudant 查询结果中省略嵌套对象中的字段?

How to omit fields in nested objects in Cloudant Query result?

我用谷歌搜索并尝试了很多,但似乎这是不可能的。也许(希望)有人知道得更多 :D

所以我在 Bluemix 上有一个 Cloudant 数据库 运行,我对它都很陌生。 查询、索引、视图...在这里有点挣扎,但到目前为止我可以成功检索文档——在我的例子中是通过 timestamp 过滤的。现在我只想让输出更方便一些。

在我的数据库中,我的文档结构如下:

{
  "_id": "0048160a463a73faaa6c90f5af027772",
  "_rev": "1-ff6255309f1b873a4e482310843a8a15",
  "timestamp": 1496275536932.6602,
  "results": {
    "lines": {
      "S1": [
        {
          "needed_key": "foo",
          "not_needed_key": 1
        }
      ],
      "S2": [
        {
          "needed_key": "bar",
          "not_needed_key": 1
        },
        {
          "needed_key": "foo_bar",
          "not_needed_key": 1
        }
      ],
      ...
    }
  },
  "station": "5002270",
  "another_not_needed_key": "something"
}

缩短后,我的 Cloudant 选择器看起来有点像这样:

{
  "selector": {
    "$and": [{
      "timestamp": {
        "$gte": from,
        "$lt": to
      },       
      "results.lines": {
        "$ne": {}
      }
    ]},
  "fields": [
    "_id",
    "timestamp",
    "station",
    "results"
  ],
  ...
}

了解 "another_not_needed_key" 为何不在 fields 中,因为,好吧,我不需要该信息。现在我想对 lines 数组对象中不需要的字段做同样的事情。

我在某处读到过,对于数组,类似于

"results.lines.S1.[].needed_key"

因为 selector 是可能的,虽然我什至不确定我是否得到任何测试结果。不管怎样:

问题:

  1. Will/should 以上对 fields 也有效? IE。它应该只输出 "S1" 数组嵌套对象中任何对象的 "needed_key" 吗?还没有成功。
  2. 我能以某种方式概括 "S1" 吗?与数组的所有对象的 [] 一样,我想寻址 lines 中的所有键。因为:有些可能包含 "S1" 作为键,有些则没有。总的来说,这里有七个可能的键,组合不同。

如果有任何不清楚的地方,我很乐意提供更多信息。提前致谢!

  1. 否 :( 使用[] shorthand 和文本类型的索引将在查询时输出数组的全部内容。

  2. 不在 Cloudant Query 中,不 :( 您可以做的最好的事情可能是将数据结构更改为嵌套数组的位置,但这无助于过滤投影值。

  3. 您的查询非常复杂,可能需要创建程序化搜索索引(即,在设计文档中,而不是通过 Cloudant 查询):https://console.ng.bluemix.net/docs/services/Cloudant/api/search.html#search(如果这听起来令人困惑,那么下面是更多上下文)。

概括地说,这取决于您如何通过 Cloudant Query 为数据编制索引。有两种方式:"type": "json""type": "text"。 text-type 可以使用 [] 表示法,而 json-type 不能。我将解释当前的 json 类型方法,并将使用文本类型信息进行更新。这也是一个很好的主题:

稍微回顾一下:在 Cloudant 中,您实际上不能进行任何即席查询,因为您已经走了这么远,所以您很清楚这一点。在 Cloudant/CouchDB 中,必须存在索引才能查询任何内容。 (默认情况下,您会在 "_id" 上获得主索引。)另外,还有多个索引引擎:1. 用于创建二级索引的传统基于地图的视图,2. Lucene 搜索索引,以及 3. 地理空间索引。

Cloudant Query 抽象了这个先索引后查询系统的一部分,但您仍然需要告诉它索引什么以及如何索引。它可以创建两种类型的索引:"json"(对应上面的#1)和"text"(上面的#2)。

根据您所观察到的行为,您似乎已经在 Cloudant 查询中创建了一个 json 类型的索引,并且针对该索引发出了选择器语句。这是您可以使用该方法获得的最接近结果:

json-类型索引:

{
  "index": {
    "fields": [
      "_id",
      "timestamp",
      "station",
      "results"
    ]
  },
  "type": "json"
}

json-类型选择器

{
  "selector": {
    "_id": {
      "$gt": 0
    }
  },
  "fields": [
    "_id",
    "timestamp",
    "station",
    "results.lines.S1.0.needed_key",
    "results.lines.S2.0.needed_key",
    "results.lines.S2.1.needed_key"
  ],
  "sort": [
    {
      "_id": "asc"
    }
  ]
}

输出:

{
 "_id": "fd298368a7a344b217698677f3f5a07d",
 "timestamp": 1496275536932.6602,
 "station": "5002270",
 "results": {
  "lines": {
   "S1": {
    "0": {
     "needed_key": "foo"
    }
   },
   "S2": {
    "0": {
     "needed_key": "bar"
    },
    "1": {
     "needed_key": "foo_bar"
    }
   }
  }
 }
}

不幸的是,json 类型的方法要求您知道事物是如何嵌套的。

文本类型的 CQ 方法无法满足您当前的需求,但这是我相信您可以获得的最接近的方法:

文本类型索引

{
  "index": {
    "fields": [
      {"name": "_id", "type": "string"},
      {"name": "timestamp", "type": "number"},
      {"name": "station", "type": "string"},
      {"name":"results.lines.S1.[].needed_key", "type": "string"}
    ]
  },
  "type": "text"
}

文本类型选择器(已更新以显示更有趣的查询)

{
  "selector": {
    "results.lines.S1": {
      "$elemMatch": {"needed_key": "foo"}
    }
  },
  "fields": [
    "_id",
    "timestamp",
    "station",
    "results.lines.S1"
  ]
}

输出

{
 "_id": "fd298368a7a344b217698677f3f5a07d",
 "timestamp": 1496275536932.6602,
 "station": "5002270",
 "results": {
  "lines": {
   "S1": [
    {
     "needed_key": "foo",
     "not_needed_key": 1
    }
   ]
  }
 }
}

希望对您有所帮助。