1

我正在使用 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 的新手。

4

1 回答 1

2

如果您的用例按照我认为的方式工作,您可以修改您的 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
}
于 2013-05-04T17:43:40.793 回答