有没有一种方法可以使用 QueryBuilder 将 Map<String,Object> 插入到 Cassandra Table 上以获得动态 table(Table with no model class)

Is there a way we can insert a Map<String,Object> onto the Cassandra Table using QueryBuilder for a dynamic table(Table with no model class)

public int save(String tableName, Map<String, Object> dataMap) throws IllegalAccessException {
    SimpleStatement saveStatement = QueryBuilder.insertInto(tableName).values()
            



    return 1;

}

我尝试了 QueryBuilder 的其他内置方法来整体保存地图值,但如果使用“values()”方法,则只能使用 map 类型的地图来保存数据,而且我已经有一个 map。这需要为动态 table p.s 完成。我对动态表不太熟悉。我尝试使用 return 类型整数的另一种方法是

public int save(String tableName, Map<String, Object> dataMap) throws IllegalAccessException {



    SimpleStatement updateStatement = QueryBuilder.update(tableName)
            .set(appendSet(dataMap))
            .where(appendWhere(domainId))
            .build();
    log.info(updateStatement.getQuery());

    return 1;
}
private Iterable<Assignment> appendSet(Map<String, Object> dataMap) throws IllegalAccessException {
    List<Assignment> assignments = new ArrayList<>();
    for (Field field : dataMap.getClass().getDeclaredFields()) {
        if (!field.getName().equals("key")) {
            try {
                field.setAccessible(true);
                if (field.get(dataMap) != null) {
                    if (field.getType().equals(Long.class)) {
                        assignments.add(Assignment.setColumn(field.getName(), literal(Long.valueOf(field.get(dataMap).toString()))));
                    } else {
                        assignments.add(Assignment.setColumn(field.getName(), literal(field.get(dataMap))));
                    }
                }
            } catch (IllegalAccessException e) {
                log.catching(e);
            }
        }
    }
    return assignments;
}

private Iterable<Relation> appendWhere(Object key) {
    List<Relation> relations = new ArrayList<>();
    for (Field field : key.getClass().getDeclaredFields()) {
        try {
            field.setAccessible(true);
            if (field.get(key) != null) {
                if (field.getType().equals(Long.class)) {
                    relations.add(Relation.column(field.getName()).isEqualTo(literal(Long.valueOf(field.get(key).toString()))));
                } else {
                    relations.add(Relation.column(field.getName()).isEqualTo(literal(field.get(key))));
                }
            }
        } catch (IllegalAccessException e) {
            log.catching(e);
        }
    }
    return relations;
}

这可能也没有成功。我需要使用保存方法 return 一个整数,但我无法弄清楚如何使用 QueryBuilders 或 CassandraTemplate 将映射值插入到 cassandra table 本身。我正在使用 Cassandra 数据库,我的 table 是动态的。谁能给我推荐一篇好文章或其他什么?我找到了一些文章,但这些文章并没有帮助我将映射键值对插入 table,所以我很费力。任何帮助将不胜感激。

Cassandra 数据建模提醒

Cassandra 没有动态 table 之类的东西,它使用严格的模式。我会争辩说,如果你没有找到任何样本,那是因为它是一个反模式。

对于 Cassandra 数据库,您首先要设计查询,然后才定义 table,因为 **您只能过滤主键中的字段(where 子句的一部分)。我提到这个是因为 Iterable<Relation> appendWhere(Object key) 是可疑的,Cassandra 中没有连接也没有关系。

如果对同一数据出现新查询,则将数据复制到另一个 table(是的,对于关系型或面向文档的情况不同)

在您的应用程序初始化时,您 prepare 您的(静态)语句来验证语法并与服务器共享 PrepareStatementID

@PostConstruct
public void prepareStatements() {
   PreparedStatement  stmtCreateUser = 
   session.prepare(QueryBuilder.insertInto(USER_TABLENAME)
                .value(USER_EMAIL, QueryBuilder.bindMarker())
                .value(USER_FIRSTNAME, QueryBuilder.bindMarker())
                .value(USER_LASTNAME, QueryBuilder.bindMarker())
                .ifNotExists().build());
}

^ 注意到定义中使用的常量。稍后当您为额外的 table 重用列名或重命名列时,调试起来会更容易。

给定一个 table :

CREATE TABLE IF NOT EXISTS users_by_city (
    city name,
    firstname text,
    lastname text,
    email text,
    PRIMARY KEY ((city), lastname, firstname, email)
);

合法但不推荐:

// This query is legal but never forget the where clause or you do full scan cluster
SELECT [fields] FROM users_by_city;

// This query is legal as you provide the partition in the where clause but having * in the select is hazardous if columns are added later.
SELECT * FROM users_by_city WHERE city=?

法律查询

SELECT firstname,lastname,email FROM users_by_city WHERE city=?

SELECT firstname,email FROM users_by_city WHERE city=? and lastname=?

// order is important
SELECT firstname,email FROM users_by_city WHERE city=? and lastname=? and firstname=?

非法查询

// city is required in PK
SELECT firstname,email FROM users_by_city WHERE lastname=? and firstname=?

// order of cluster columns are important
SELECT firstname,email FROM users_by_city WHERE a city=?  and firstname=?

实施细节

所有这些提醒(抱歉,如果您已经知道所有这些想法,这些想法可能会在稍后出现...)这里有一些想法。

QueryBuilder 已经是动态构建查询的构建器,但查看您的代码您可以想到

插入

public SimpleStatement insertInto(String keyspace, 
  String tableName, Map<String, Object> fields) {
  return QueryBuilder.insertInto(keyspace, tableName)
                     .values(fields.entrySet()
                         .stream().collect(Collectors.toMap(
                             entry -> entry.getKey(), 
                             entry -> QueryBuilder.literal(entry.getValue()))))
                     .build();
}

SELECT

public SimpleStatement selectFrom(String keyspace, String tableName, Map<String, Relation> fields) {
        return QueryBuilder.selectFrom(keyspace, tableName)
                           .columns(fields.keySet())
                           .where(fields.values())
                           .build();
        
    }

额外资源