【问题标题】:How to execute ranged query in cassandra with astyanax and composite column如何使用 astyanax 和复合列在 cassandra 中执行范围查询
【发布时间】:2013-03-03 14:41:12
【问题描述】:

我正在使用 cassandra 和 astyanax 开发博客。当然,这只是一个练习。

我以这种方式对 CF_POST_INFO 列族进行了建模:

private static class PostAttribute {

    @Component(ordinal = 0)
    UUID postId;

    @Component(ordinal = 1)
    String category;

    @Component
    String name;

    public PostAttribute() {}

    private PostAttribute(UUID postId, String category, String name) {
        this.postId = postId;
        this.category = category;
        this.name = name;
    }

    public static PostAttribute of(UUID postId, String category, String name) {
        return new PostAttribute(postId, category, name);
    }
}

    private static AnnotatedCompositeSerializer<PostAttribute> postSerializer = new AnnotatedCompositeSerializer<>(PostAttribute.class);

private static final ColumnFamily<String, PostAttribute> CF_POST_INFO =
        ColumnFamily.newColumnFamily("post_info", StringSerializer.get(), postSerializer);

一个帖子就是这样保存的:

        MutationBatch m = keyspace().prepareMutationBatch();

    ColumnListMutation<PostAttribute> clm = m.withRow(CF_POST_INFO, "posts")
            .putColumn(PostAttribute.of(post.getId(), "author", "id"), post.getAuthor().getId().get())
            .putColumn(PostAttribute.of(post.getId(), "author", "name"), post.getAuthor().getName())
            .putColumn(PostAttribute.of(post.getId(), "meta", "title"), post.getTitle())
            .putColumn(PostAttribute.of(post.getId(), "meta", "pubDate"), post.getPublishingDate().toDate());

    for(String tag : post.getTags()) {
        clm.putColumn(PostAttribute.of(post.getId(), "tags", tag), (String) null);
    }

    for(String category : post.getCategories()) {
        clm.putColumn(PostAttribute.of(post.getId(), "categories", category), (String)null);
    }

这个想法是有一些像一段时间桶一样的行(例如,每月或每年一行)。

例如,现在如果我想获取最后 5 个帖子,我该如何进行愤怒查询?我可以根据帖子 ID (UUID) 执行愤怒查询,但如果不执行另一个查询来获取它们,我不知道可用的帖子 ID。这里的 cassandra 最佳实践是什么?

当然欢迎任何关于数据模型的建议,我是 cassandra 的新手。

【问题讨论】:

    标签: cassandra composite-key astyanax


    【解决方案1】:

    如果您的用例按照我认为的方式工作,您可以修改您的 PostAttribute 以便第一个组件是 TimeUUID,这样您就可以将其存储为时间序列数据,并且您可以轻松提取最旧的 5 或最新的 5 使用标准技术。无论如何...这里是我的示例,因为如果您已经在使用复合材料,您实际上并不需要创建多个列。

    public class PostInfo {
        @Component(ordinal = 0)
        protected UUID timeUuid;
    
        @Component(ordinal = 1)
        protected UUID postId;
    
        @Component(ordinal = 2)
        protected String category;
    
        @Component(ordinal = 3)
        protected String name;
    
        @Component(ordinal = 4)
        protected UUID authorId;
    
        @Component(ordinal = 5)
        protected String authorName;
    
        @Component(ordinal = 6)
        protected String title;
    
        @Component(ordinal = 7)
        protected Date published;
    
        public PostInfo() {}
    
        private PostInfo(final UUID postId, final String category, final String name, final UUID authorId, final String authorName, final String title, final Date published) {
            this.timeUuid = TimeUUIDUtils.getUniqueTimeUUIDinMillis();
            this.postId = postId;
            this.category = category;
            this.name = name;
            this.authorId = authorId;
            this.authorName = authorName;
            this.title = title;
            this.published = published;
        }
    
        public static PostInfo of(final UUID postId, final String category, final String name, final UUID authorId, final String authorName, final String title, final Date published) {
            return new PostInfo(postId, category, name, authorId, authorName, title, published);
        }
    }
    
        private static AnnotatedCompositeSerializer<PostInfo> postInfoSerializer = new AnnotatedCompositeSerializer<>(PostInfo.class);
    
    private static final ColumnFamily<String, PostInfo> CF_POSTS_TIMELINE =
            ColumnFamily.newColumnFamily("post_info", StringSerializer.get(), postInfoSerializer);
    

    你应该这样保存它:

    MutationBatch m = keyspace().prepareMutationBatch();
    
    ColumnListMutation<PostInfo> clm = m.withRow(CF_POSTS_TIMELINE, "all" /* or whatever makes sense for you such as year or month or whatever */)
            .putColumn(PostInfo.of(post.getId(), post.getCategory(), post.getName(), post.getAuthor().getId(), post.getAuthor().getName(), post.getTitle(), post.getPublishedOn()), /* maybe just null bytes as column value */)
    m.execute();
    

    那么你可以这样查询:

    OperationResult<ColumnList<PostInfo>> result = getKeyspace()
        .prepareQuery(CF_POSTS_TIMELINE)
        .getKey("all" /* or whatever makes sense like month, year, etc */)
        .withColumnRange(new RangeBuilder()
            .setLimit(5)
            .setReversed(true)
            .build())
        .execute();
    ColumnList<PostInfo> columns = result.getResult();
    for (Column<PostInfo> column : columns) {
        // do what you need here
    }
    

    【讨论】:

    • 谢谢,是的,这正是我想要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    • 2020-06-03
    • 2013-11-28
    • 1970-01-01
    • 2012-03-13
    相关资源
    最近更新 更多