/** * Reads a page from a "shared" DynamoDB table. Shared tables are tables that have global secondary indexes * and can contain the objects of multiple apps. * @param <P> type of object * @param appid the app identifier (name) * @param pager a {@link Pager} * @return the id of the last object on the page, or null. */ public static <P extends ParaObject> List<P> readPageFromSharedTable(String appid, Pager pager) { LinkedList<P> results = new LinkedList<>(); if (StringUtils.isBlank(appid)) { return results; } Page<Item, QueryOutcome> items = queryGSI(appid, pager); if (items != null) { for (Item item : items) { P obj = ParaObjectUtils.setAnnotatedFields(item.asMap()); if (obj != null) { results.add(obj); } } } if (!results.isEmpty() && pager != null) { pager.setLastKey(results.peekLast().getId()); } return results; }
private static Page<Item, QueryOutcome> queryGSI(String appid, Pager p) { Pager pager = (p != null) ? p : new Pager(); Index index = getSharedIndex(); QuerySpec spec = new QuerySpec(). withMaxPageSize(pager.getLimit()). withMaxResultSize(pager.getLimit()). withKeyConditionExpression(Config._APPID + " = :aid"). withValueMap(new ValueMap().withString(":aid", appid)); if (!StringUtils.isBlank(pager.getLastKey())) { spec = spec.withExclusiveStartKey(new KeyAttribute(Config._APPID, appid), // HASH/PARTITION KEY new KeyAttribute(Config._ID, pager.getLastKey()), // RANGE/SORT KEY new KeyAttribute(Config._KEY, getKeyForAppid(pager.getLastKey(), appid))); // TABLE PRIMARY KEY } return index != null ? index.query(spec).firstPage() : null; }
private static void findRepliesUsingAFilterExpression(String forumName, String threadSubject) { Table table = dynamoDB.getTable(tableName); String replyId = forumName + "#" + threadSubject; QuerySpec spec = new QuerySpec() .withProjectionExpression("Message, ReplyDateTime, PostedBy") .withKeyConditionExpression("Id = :v_id") .withFilterExpression("PostedBy = :v_postedby") .withValueMap(new ValueMap() .withString(":v_id", replyId) .withString(":v_postedby", "User B")); ItemCollection<QueryOutcome> items = table.query(spec); System.out.println("\nfindRepliesUsingAFilterExpression results:"); Iterator<Item> iterator = items.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } }
@Override public boolean queryRelationExists(String relationHashKey, String relationRangeKey) { Table table = dynamoDB.getTable(this.groupGraphTableName); QuerySpec querySpec = new QuerySpec() .withKeyConditionExpression("subject = :k_subject and object_relation = :k_object_relation") .withValueMap(new ValueMap() .withString(":k_subject", relationHashKey) .withString(":k_object_relation", relationRangeKey) ) .withMaxResultSize(1) .withConsistentRead(true); DynamoDbCommand<ItemCollection<QueryOutcome>> cmd = new DynamoDbCommand<>("queryRelation", () -> queryTable(table, querySpec), () -> { throw new RuntimeException("queryRelation"); }, dynamodbNamespaceGraphQueryHystrix, metrics); // can't use getLastLowLevelResult directly; it's false unless the outcome is iterated first :| return cmd.execute().iterator().hasNext(); }
@Override public Optional<Group> loadByKey(String key) { Table table = dynamoDB.getTable(this.groupTableName); QuerySpec querySpec = new QuerySpec() .withKeyConditionExpression(HASH_KEY + " = :k_app_key") .withValueMap(new ValueMap() .withString(":k_app_key", key) ) .withMaxResultSize(1) .withConsistentRead(true); DynamoDbCommand<ItemCollection<QueryOutcome>> cmd = new DynamoDbCommand<>("loadByKey", () -> queryTable(table, querySpec), () -> { throw new RuntimeException("loadByKey"); }, dynamodbNamespaceGraphQueryHystrix, metrics); final ItemCollection<QueryOutcome> items = cmd.execute(); final IteratorSupport<Item, QueryOutcome> iterator = items.iterator(); if (iterator.hasNext()) { return Optional.of(GroupSupport.toGroup(iterator.next().getString("json"))); } return Optional.empty(); }
@Override public List<Feature> loadFeatures(String group) { logger.info("{}", kvp("op", "loadFeatures", "group", group)); List<Feature> features = Lists.newArrayList(); Table table = dynamoDB.getTable(featureTableName); QuerySpec querySpec = new QuerySpec() .withKeyConditionExpression(HASH_KEY + " = :k_" + HASH_KEY) .withValueMap(new ValueMap().withString(":k_" + HASH_KEY, group)) .withConsistentRead(true); DynamoDbCommand<ItemCollection<QueryOutcome>> cmd = new DynamoDbCommand<>("loadFeatures", () -> queryTable(table, querySpec), () -> { throw new RuntimeException("loadFeatureById"); }, hystrixReadConfiguration, metrics); ItemCollection<QueryOutcome> items = cmd.execute(); for (Page<Item, QueryOutcome> page : items.pages()) { page.forEach(item -> features.add(FeatureSupport.toFeature(item.getString("json")))); } return features; }
private <V> List<V> toList(QueryOutcome outcome, Class<V> type) { List<Item> items = outcome.getItems(); List<V> result = new ArrayList<V>(items.size()); for ( Item item : items ) { result.add(fromItem(_encryption.decrypt(item), type)); } return Collections.unmodifiableList(result); }
private QueryOutcome query(Object hk, QuerySpec querySpec, PageIterator pageIterator) { if ( null == _convertMarker ) { throw new IllegalStateException("Index must first be initialized with ConvertMarker"); } if ( pageIterator.getPageSize() <= 0 ) { return new QueryOutcome(new QueryResult()); } ItemCollection<QueryOutcome> itemCollection = maybeBackoff(true, () -> _query.query(withMarker(querySpec.withHashKey(_hkName, hk), pageIterator, hk))); if ( null != itemCollection ) { Iterator<Page<Item, QueryOutcome>> iterator = itemCollection.pages().iterator(); if ( iterator.hasNext() ) { QueryOutcome outcome = maybeBackoff(true, () -> iterator.next().getLowLevelResult()); QueryResult result = outcome.getQueryResult(); if ( null != pageIterator.getMarker() && null != result.getItems() && result.getItems().size() > 0 ) { pageIterator.setPrevMarker(toMarker(result.getItems().get(0), true)); } else { pageIterator.setPrevMarker(null); } Map<String,AttributeValue> lastKey = result.getLastEvaluatedKey(); if ( null != lastKey && ! lastKey.isEmpty() ) { pageIterator.setMarker(toMarker(lastKey, true)); } else { pageIterator.setMarker(null); } return outcome; } } pageIterator.setPrevMarker(null); pageIterator.setMarker(null); return new QueryOutcome(new QueryResult()); }
private static void findRepliesInLast15DaysWithConfig( String tableName, String forumName, String threadSubject) { String replyId = forumName + "#" + threadSubject; long twoWeeksAgoMilli = (new Date()).getTime() - (15L * 24L * 60L * 60L * 1000L); Date twoWeeksAgo = new Date(); twoWeeksAgo.setTime(twoWeeksAgoMilli); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); String twoWeeksAgoStr = df.format(twoWeeksAgo); Table table = dynamoDB.getTable(tableName); QuerySpec querySpec = new QuerySpec() .withKeyConditionExpression("Id = :v1 and ReplyDateTime > :v2") .withValueMap(new ValueMap() .withString(":v1", replyId) .withString(":v2", twoWeeksAgoStr)) .withProjectionExpression("Message, ReplyDateTime, PostedBy"); ItemCollection<QueryOutcome> items = table.query(querySpec); Iterator<Item> iterator = items.iterator(); System.out.println("Query: printing results..."); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } }
private static void findRepliesForAThreadSpecifyOptionalLimit(String forumName, String threadSubject) { Table table = dynamoDB.getTable(tableName); String replyId = forumName + "#" + threadSubject; QuerySpec spec = new QuerySpec() .withKeyConditionExpression("Id = :v_id") .withValueMap(new ValueMap() .withString(":v_id", replyId)) .withMaxPageSize(1); ItemCollection<QueryOutcome> items = table.query(spec); System.out.println("\nfindRepliesForAThreadSpecifyOptionalLimit results:"); // Process each page of results int pageNum = 0; for (Page<Item, QueryOutcome> page : items.pages()) { System.out.println("\nPage: " + ++pageNum); // Process each item on the current page Iterator<Item> item = page.iterator(); while (item.hasNext()) { System.out.println(item.next().toJSONPretty()); } } }
private static void findRepliesInLast15DaysWithConfig(String forumName, String threadSubject) { Table table = dynamoDB.getTable(tableName); long twoWeeksAgoMilli = (new Date()).getTime() - (15L*24L*60L*60L*1000L); Date twoWeeksAgo = new Date(); twoWeeksAgo.setTime(twoWeeksAgoMilli); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); String twoWeeksAgoStr = df.format(twoWeeksAgo); String replyId = forumName + "#" + threadSubject; QuerySpec spec = new QuerySpec() .withProjectionExpression("Message, ReplyDateTime, PostedBy") .withKeyConditionExpression("Id = :v_id and ReplyDateTime <= :v_reply_dt_tm") .withValueMap(new ValueMap() .withString(":v_id", replyId) .withString(":v_reply_dt_tm", twoWeeksAgoStr)); ItemCollection<QueryOutcome> items = table.query(spec); System.out.println("\nfindRepliesInLast15DaysWithConfig results:"); Iterator<Item> iterator = items.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } }
private static void findRepliesPostedWithinTimePeriod(String forumName, String threadSubject) { Table table = dynamoDB.getTable(tableName); long startDateMilli = (new Date()).getTime() - (15L*24L*60L*60L*1000L); long endDateMilli = (new Date()).getTime() - (5L*24L*60L*60L*1000L); java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); String startDate = df.format(startDateMilli); String endDate = df.format(endDateMilli); String replyId = forumName + "#" + threadSubject; QuerySpec spec = new QuerySpec() .withProjectionExpression("Message, ReplyDateTime, PostedBy") .withKeyConditionExpression("Id = :v_id and ReplyDateTime between :v_start_dt and :v_end_dt") .withValueMap(new ValueMap() .withString(":v_id", replyId) .withString(":v_start_dt", startDate) .withString(":v_end_dt", endDate)); ItemCollection<QueryOutcome> items = table.query(spec); System.out.println("\nfindRepliesPostedWithinTimePeriod results:"); Iterator<Item> iterator = items.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } }
public MAVLinkRecordIterable(IteratorSupport<Item, QueryOutcome> it) { this.itemIterator = it; }
private ItemCollection<QueryOutcome> queryTable(Table table, QuerySpec querySpec) { return table.query(querySpec); }
private static int toCount(QueryOutcome outcome) { Integer result = outcome.getQueryResult().getCount(); return ( null == result ) ? 0 : result.intValue(); }
private List<T> toList(QueryOutcome outcome) { return toList(outcome, _clazz); }
/** * Deletes all objects in a shared table, which belong to a given appid, by scanning the GSI. * @param appid app id */ public static void deleteAllFromSharedTable(String appid) { if (StringUtils.isBlank(appid) || !isSharedAppid(appid)) { return; } Pager pager = new Pager(50); List<WriteRequest> allDeletes = new LinkedList<>(); Page<Item, QueryOutcome> items; // read all phase do { items = queryGSI(appid, pager); if (items == null) { break; } for (Item item : items) { String key = item.getString(Config._KEY); // only delete rows which belong to the given appid if (StringUtils.startsWith(key, appid.trim())) { logger.debug("Preparing to delete '{}' from shared table, appid: '{}'.", key, appid); pager.setLastKey(item.getString(Config._ID)); allDeletes.add(new WriteRequest().withDeleteRequest(new DeleteRequest(). withKey(Collections.singletonMap(Config._KEY, new AttributeValue(key))))); } } } while (items.iterator().hasNext()); // delete all phase final int maxItems = 20; int batchSteps = (allDeletes.size() > maxItems) ? (allDeletes.size() / maxItems) + 1 : 1; List<WriteRequest> reqs = new LinkedList<>(); Iterator<WriteRequest> it = allDeletes.iterator(); String tableName = getTableNameForAppid(appid); for (int i = 0; i < batchSteps; i++) { while (it.hasNext() && reqs.size() < maxItems) { reqs.add(it.next()); } if (reqs.size() > 0) { logger.info("Deleting {} items belonging to app '{}', from shared table (page {}/{})...", reqs.size(), appid, i + 1, batchSteps); batchWrite(Collections.singletonMap(tableName, reqs)); } reqs.clear(); } }
public static void main(String[] args) { AmazonDynamoDBClient client = new AmazonDynamoDBClient(); client.setEndpoint("http://localhost:8000"); DynamoDB dynamoDB = new DynamoDB(client); Table table = dynamoDB.getTable("Movies"); HashMap<String, String> nameMap = new HashMap<String, String>(); nameMap.put("#yr", "year"); HashMap<String, Object> valueMap = new HashMap<String, Object>(); valueMap.put(":yyyy", 1985); QuerySpec querySpec = new QuerySpec() .withKeyConditionExpression("#yr = :yyyy") .withNameMap(new NameMap().with("#yr", "year")) .withValueMap(valueMap); ItemCollection<QueryOutcome> items = table.query(querySpec); Iterator<Item> iterator = items.iterator(); Item item = null; System.out.println("Movies from 1985"); while (iterator.hasNext()) { item = iterator.next(); System.out.println(item.getNumber("year") + ": " + item.getString("title")); } valueMap.put(":yyyy", 1992); valueMap.put(":letter1", "A"); valueMap.put(":letter2", "L"); querySpec .withProjectionExpression("#yr, title, info.genres, info.actors[0]") .withKeyConditionExpression("#yr = :yyyy and title between :letter1 and :letter2") .withNameMap(nameMap) .withValueMap(valueMap); items = table.query(querySpec); iterator = items.iterator(); System.out.println("Movies from 1992 - titles A-L, with genres and lead actor"); while (iterator.hasNext()) { item = iterator.next(); System.out.println(item.toString()); } }
private static void findRepliesForAThread(String forumName, String threadSubject) { Table table = dynamoDB.getTable(tableName); String replyId = forumName + "#" + threadSubject; QuerySpec spec = new QuerySpec() .withKeyConditionExpression("Id = :v_id") .withValueMap(new ValueMap() .withString(":v_id", replyId)); ItemCollection<QueryOutcome> items = table.query(spec); System.out.println("\nfindRepliesForAThread results:"); Iterator<Item> iterator = items.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } }
public static void queryIndex(String indexName) { Table table = dynamoDB.getTable(tableName); System.out.println ("\n***********************************************************\n"); System.out.print("Querying index " + indexName + "..."); Index index = table.getIndex(indexName); ItemCollection<QueryOutcome> items = null; QuerySpec querySpec = new QuerySpec(); if (indexName == "CreateDateIndex") { System.out.println("Issues filed on 2013-11-01"); querySpec.withKeyConditionExpression("CreateDate = :v_date and begins_with(IssueId, :v_issue)") .withValueMap(new ValueMap() .withString(":v_date","2013-11-01") .withString(":v_issue","A-")); items = index.query(querySpec); } else if (indexName == "TitleIndex") { System.out.println("Compilation errors"); querySpec.withKeyConditionExpression("Title = :v_title and begins_with(IssueId, :v_issue)") .withValueMap(new ValueMap() .withString(":v_title","Compilation error") .withString(":v_issue","A-")); items = index.query(querySpec); } else if (indexName == "DueDateIndex") { System.out.println("Items that are due on 2013-11-30"); querySpec.withKeyConditionExpression("DueDate = :v_date") .withValueMap(new ValueMap() .withString(":v_date","2013-11-30")); items = index.query(querySpec); } else { System.out.println("\nNo valid index name provided"); return; } Iterator<Item> iterator = items.iterator(); System.out.println("Query: printing results..."); while (iterator.hasNext()) { System.out.println(iterator.next().toJSONPretty()); } }