2015-02-18 7 views
5

Ich arbeite mit The AWS Command Line Interface for DynamoDB.Wie vereinfacht man AWS DynamoDB Abfrage JSON-Ausgabe von der Kommandozeile?

Wenn wir ein Element abfragen, erhalten wir eine sehr detaillierte JSON-Ausgabe. Sie erhalten so etwas wie diese (es von den get-item gebaut, um wurde fast auf Vollständigkeit (der NULL Typ weggelassen wurde) aws command line help:

{ 
    "Count": 1, 
    "Items": [ 
     { 
      "Id": { 
       "S": "app1" 
      }, 
      "Parameters": { 
       "M": { 
        "nfs": { 
         "M": { 
          "IP" : { 
           "S" : "172.16.0.178" 
          }, 
          "defaultPath": { 
           "S": "/mnt/ebs/" 
          }, 
          "key": { 
           "B": "dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk" 
          }, 
          "activated": { 
           "BOOL": true 
          } 
         } 
        }, 
        "ws" : { 
         "M" : { 
          "number" : { 
           "N" : "5" 
          }, 
          "values" : { 
           "L" : [ 
            { "S" : "12253456346346"}, 
            { "S" : "23452353463464"}, 
            { "S" : "23523453461232"}, 
            { "S" : "34645745675675"}, 
            { "S" : "46456745757575"} 
           ] 
          } 
         } 
        } 
       } 
      }, 
      "Oldtypes": { 
       "typeSS" : {"SS" : ["foo", "bar", "baz"]}, 
       "typeNS" : {"NS" : ["0", "1", "2", "3", "4", "5"]}, 
       "typeBS" : {"BS" : ["VGVybWluYXRvcgo=", "VGVybWluYXRvciAyOiBKdWRnbWVudCBEYXkK", "VGVybWluYXRvciAzOiBSaXNlIG9mIHRoZSBNYWNoaW5lcwo=", "VGVybWluYXRvciA0OiBTYWx2YXRpb24K","VGVybWluYXRvciA1OiBHZW5lc2lzCg=="]} 
      } 
     } 
    ], 
    "ScannedCount": 1, 
    "ConsumedCapacity": null 
} 

Gibt es eine Möglichkeit, eine einfachere Ausgabe für den Items Teil zu bekommen? wie folgt aus:..

{ 
    "ConsumedCapacity": null, 
    "Count": 1, 
    "Items": [ 
     { 
      "Id": "app1", 
      "Parameters": { 
       "nfs": { 
        "IP": "172.16.0.178", 
        "activated": true, 
        "defaultPath": "/mnt/ebs/", 
        "key": "dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk" 
       }, 
       "ws": { 
        "number": 5, 
        "values": ["12253456346346","23452353463464","23523453461232","34645745675675","46456745757575"] 
       } 
      }, 
      "Oldtypes": { 
       "typeBS": ["VGVybWluYXRvcgo=", "VGVybWluYXRvciAyOiBKdWRnbWVudCBEYXkK", "VGVybWluYXRvciAzOiBSaXNlIG9mIHRoZSBNYWNoaW5lcwo=", "VGVybWluYXRvciA0OiBTYWx2YXRpb24K", "VGVybWluYXRvciA1OiBHZW5lc2lzCg=="], 
       "typeNS": [0, 1, 2, 3, 4, 5], 
       "typeSS": ["foo","bar","baz"] 
      } 
     } 
    ], 
    "ScannedCount": 1 
} 

Es gibt nichts, hilfreich bei der dynamodb - AWS CLI 1.7.10 documentation

Wir müssen das Ergebnis von der Kommandozeile bekommen ich bin bereit, andere Kommandozeilen-Tools li verwenden ke jq wenn nötig, aber eine solche jq Zuordnung scheint mir kompliziert.


Update 1: jq basierte Lösung (mit Hilfe von DanielH Antwort)

Mit jq es ist einfach, aber nicht ganz hübsch, man kann so etwas tun:

$> aws dynamodb query --table-name ConfigCatalog --key-conditions '{ "Id" : {"AttributeValueList": [{"S":"app1"}], "ComparisonOperator": "EQ"}}' | jq -r '.Items[0].Parameters.M."nfs#IP".S' 

Ergebnis wird sein: 172.16.0.178

Die jq-r option gi Sie erhalten eine rohe Ausgabe.


Update 2: jq basierte Lösung (mit Hilfe von @ jeff-mercado)

Hier ist eine aktualisierte und kommentierte Version von Jeff Mercado jq Funktion DynamoDB Ausgabe entordnen. Es wird Ihnen die erwartete Ausgabe:

$> jq -f unmarshal_dynamodb.jq ddb-query-result.json 
+0

Hmm, so ist es, dass die Schlüsselnamen ihre Typen zeigen Objekt? Wie steht "S" für Strings, "M" für Maps und "N" für Zahlen? Sie können tatsächlich etwas wirklich schönes damit machen. –

+0

Ihre 'unmarshal_dynamodb.jq' Lösung ist brilliant und der Kredit geht an Sie & @JeffMercado. Ein Fehler bei der Verwendung der '//', die ich zu lösen versucht habe, ist, dass jeder Filter, der false zurückgibt, nicht transformiert wird. Dies ist wichtig bei booleschen Werten, die tatsächlich auf "false" gesetzt sind - sie behalten die "BOOL" - oder "B" -Taste bei. Ich habe eine Zeile hinzugefügt, um dieses Problem teilweise zu lösen, habe aber noch keinen Weg gefunden, um es ohne einen zweiten Durchlauf vollständig zu reparieren: '// (Objekte | wenn hat ("BOOL") oder hat ("B") dann [false] else null end) ' Dies fügt 'false' als 1-Element-Array hinzu und muss vor der Zeile" # managing others ... "stehen. –

+1

@DaveStern: Ich habe die hier verwendete Methode überarbeitet, um Falschwerte richtig zu behandeln. Und sollte jetzt eine insgesamt sauberere Implementierung haben. –

Antwort

6

Sie können die Werte rekursiv mit einer gut gestalteten Funktion dekodieren.Es sieht aus wie die Tastennamen auf einen Typ entsprechen:

S -> string 
N -> number 
M -> map 

Griff jedem der Fälle Sie, wenn möglich, entschlüsseln wollen, sonst ist es herauszufiltern. Sie können dazu die verschiedenen type filters und die alternative operator verwenden.

$ cat input.json 
{ 
    "Count": 1, 
    "Items": [ 
    { 
     "Id": { "S": "app1" }, 
     "Parameters": { 
     "M": { 
      "nfs#IP": { "S": "192.17.0.13" }, 
      "maxCount": { "N": "1" }, 
      "nfs#defaultPath": { "S": "/mnt/ebs/" } 
     } 
     } 
    } 
    ], 
    "ScannedCount": 1, 
    "ConsumedCapacity": null 
} 
$ cat ~/.jq 
def decode_ddb: 
    def _sprop($key): select(keys == [$key])[$key];     # single property objects only 
     ((objects | { value: _sprop("S") })       # string (from string) 
    // (objects | { value: _sprop("B") })       # blob (from string) 
    // (objects | { value: _sprop("N") | tonumber })    # number (from string) 
    // (objects | { value: _sprop("BOOL") })      # boolean (from boolean) 
    // (objects | { value: _sprop("M") | map_values(decode_ddb) }) # map (from object) 
    // (objects | { value: _sprop("L") | map(decode_ddb) })   # list (from encoded array) 
    // (objects | { value: _sprop("SS") })       # string set (from string array) 
    // (objects | { value: _sprop("NS") | map(tonumber) })   # number set (from string array) 
    // (objects | { value: _sprop("BS") })       # blob set (from string array) 
    // (objects | { value: map_values(decode_ddb) })    # all other non-conforming objects 
    // (arrays | { value: map(decode_ddb) })      # all other non-conforming arrays 
    // { value: . }).value           # everything else 
    ; 
$ jq 'decode_ddb' input.json 
{ 
    "Count": 1, 
    "Items": [ 
    { 
     "Id": "app1", 
     "Parameters": { 
     "nfs#IP": "192.17.0.13", 
     "maxCount": 1, 
     "nfs#defaultPath": "/mnt/ebs/" 
     } 
    } 
    ], 
    "ScannedCount": 1, 
    "ConsumedCapacity": null 
} 
+0

Dank der Hilfe von @ Jeff-Mercado. Ich habe eine erweiterte Version seiner Funktion 'decode_ddb.jq' als Update des ursprünglichen Posts gepostet. – herve

0

Soweit ich weiß:

$> cat unmarshal_dynamodb.jq 
def unmarshal_dynamodb: 
    # DynamoDB string type 
    (objects | .S) 

    # DynamoDB blob type 
    // (objects | .B) 

    # DynamoDB number type 
    // (objects | .N | strings | tonumber) 

    # DynamoDB boolean type 
    // (objects | .BOOL) 

    # DynamoDB map type, recursion on each item 
    // (objects | .M | objects | with_entries(.value |= unmarshal_dynamodb)) 

    # DynamoDB list type, recursion on each item 
    // (objects | .L | arrays | map(unmarshal_dynamodb)) 

    # DynamoDB typed list type SS, string set 
    // (objects | .SS | arrays | map(unmarshal_dynamodb)) 

    # DynamoDB typed list type NS, number set 
    // (objects | .NS | arrays | map(tonumber)) 

    # DynamoDB typed list type BS, blob set 
    // (objects | .BS | arrays | map(unmarshal_dynamodb)) 

    # managing others DynamoDB output entries: "Count", "Items", "ScannedCount" and "ConsumedCapcity" 
    // (objects | with_entries(.value |= unmarshal_dynamodb)) 
    // (arrays | map(unmarshal_dynamodb)) 

    # leaves values 
    // . 
    ; 
unmarshal_dynamodb 

Wenn Sie die DynamoDB Abfrageausgabe in einer Datei speichern, ddb-query-result.json können sagen, können Sie gewünschte Ergebnis erhalten ausführen Es gibt keine andere Ausgabe wie die "ausführliche", die Sie gepostet haben. Deshalb denke ich, kann man nicht Zwischen Tools wie jq oder sed

Es gibt mehrere Vorschläge in diesem Beitrag zur Umwandlung der rohen Dynamo Daten vermeiden können:

Export data from DynamoDB

Vielleicht können Sie eine dieser Skripte anpassen in Verbindung mit jq oder sed

+0

mit 'jq' ist es einfach, aber nicht ruhig hübsch, können Sie etwas tun wie:' aws dynamodb Abfrage --Tabellenname ConfigCatalog --key-Bedingungen '{"Id": {"AttributeValueList": [{"S ":" app1 "}]," ComparisonOperator ":" EQ "}} '| jq -r '.Items [0] .Parameters.M. "nfs # IP" .S'' Ergebnis ist: '172.16.0.178'. Siehe aktualisierten Beitrag. – herve

0

hier ein anderer Ansatz. Das mag etwas brutal sein, aber es zeigt die Grundidee.

def unwanted: ["B","BOOL","M","S","L","BS","SS"]; 
def fixpath(p): [ p[] | select(unwanted[[.]]==[]) ]; 
def fixnum(p;v): 
    if p[-2]=="NS" then [p[:-2]+p[-1:],(v|tonumber)] 
    elif p[-1]=="N" then [p[:-1], (v|tonumber)] 
    else [p,v] end; 

reduce (tostream|select(length==2)) as [$p,$v] (
    {} 
    ; fixnum(fixpath($p);$v) as [$fp,$fv]  
    | setpath($fp;$fv) 
) 

Try it online!

Sample Run (unter der Annahme Filter in filter.jq und Daten in data.json)

$ jq -M -f filter.jq data.json 
{ 
    "ConsumedCapacity": null, 
    "Count": 1, 
    "Items": [ 
    { 
     "Id": "app1", 
     "Oldtypes": { 
     "typeBS": [ 
      "VGVybWluYXRvcgo=", 
      "VGVybWluYXRvciAyOiBKdWRnbWVudCBEYXkK", 
      "VGVybWluYXRvciAzOiBSaXNlIG9mIHRoZSBNYWNoaW5lcwo=", 
      "VGVybWluYXRvciA0OiBTYWx2YXRpb24K", 
      "VGVybWluYXRvciA1OiBHZW5lc2lzCg==" 
     ], 
     "typeNS": [ 
      0, 
      1, 
      2, 
      3, 
      4, 
      5 
     ], 
     "typeSS": [ 
      "foo", 
      "bar", 
      "baz" 
     ] 
     }, 
     "Parameters": { 
     "nfs": { 
      "IP": "172.16.0.178", 
      "activated": true, 
      "defaultPath": "/mnt/ebs/", 
      "key": "dGhpcyB0ZXh0IGlzIGJhc2U2NC1lbmNvZGVk" 
     }, 
     "ws": { 
      "number": 5, 
      "values": [ 
      "12253456346346", 
      "23452353463464", 
      "23523453461232", 
      "34645745675675", 
      "46456745757575" 
      ] 
     } 
     } 
    } 
    ], 
    "ScannedCount": 1 
}