PolarSPARC |
Cassandra Quick Notes :: Part - 4
Bhaskar S | *UPDATED*12/01/2023 |
Overview
In Part-1 of this article series, we performed the necessary setup, started a single-node Apache Cassandra cluster and got our hands dirty with CQL operations.
In Part-2 of this article series, we performed the necessary setup to start a 3-node Apache Cassandra cluster and got our hands dirty with some Cassandra concepts.
In Part-3 of this article series, we leverage the 3-node Apache Cassandra cluster setup and got our hands dirty with additional Cassandra concepts.
In this part, we will demonstrate how to work with Apache Cassandra via an application code using both Python and Spring Boot Java.
Hands-on with Python Cassandra Driver
Ensure the Python Cassandra driver is installed by executing the following commands:
$ sudo apt install pip3 -y
$ sudo pip3 install cassandra-driver
To setup the Python directory structure for the demonstrations, execute the following commands:
$ cd $CASSANDRA_HOME
$ mkdir -p python
$ cd $CASSANDRA_HOME/python
For the demonstration, we don't need all the nodes in the cluster running. Ensure that the single-node Apache Cassandra cluster is up and running. Else, execute the following command:
$ docker run --rm --name cas-node-1 --hostname cas-node-1 --network cassandra-db-net -p 7199:7199 -p 9042:9042 -u $(id -u $USER):$(id -g $USER) -v $CASSANDRA_HOME/data:/var/lib/cassandra/data -v $CASSANDRA_HOME/etc/cassandra:/etc/cassandra -v $CASSANDRA_HOME/logs:/opt/cassandra/logs cassandra:5.0
To import the required Python modules and initialize some variables, execute the following code snippet:
import logging from cassandra.cluster import Cluster, ExecutionProfile, EXEC_PROFILE_DEFAULT from cassandra.policies import WhiteListRoundRobinPolicy CASSANDRA_PORT = 9042 CASSANDRA_HOST = '127.0.0.1' CASSANDRA_KS = 'my_test_ks' CASSANDRA_TABLE = 'book_catalog' logging.basicConfig(format='%(asctime)s - %(message)s', level=logging.INFO)
To interact with a Cassandra cluster, one needs to create a cluster connection by providing some configuration options, such as, the load balancing strategy, the network port, the protocol version, etc. An instance of the Python class Cluster allows one to do just that. To create a connection to the single-node Cassandra cluster, execute the following code snippet:
def get_cluster_session(host, port): logging.info(f'Connecting to {host} at port {port}') profile = ExecutionProfile(load_balancing_policy=WhiteListRoundRobinPolicy([host])) cluster = Cluster(execution_profiles={EXEC_PROFILE_DEFAULT: profile}, port=port, protocol_version=5) session = cluster.connect() logging.info(f'Connection successful !!!') return cluster, session
Note that an instance of the Python class ExecutionProfile indicates the load balancing strategy.
To create and use a desired Keyspace in Cassandra, execute the following code snippet:
def set_keyspace(session, ks): logging.info(f'Checking for existence of keyspace {ks}') rows = session.execute('SELECT keyspace_name FROM system_schema.keyspaces') if ks not in [row[0] for row in rows]: session.execute(""" CREATE KEYSPACE %s WITH REPLICATION = {'class': 'SimpleStrategy', 'replication_factor': 1}; """ % ks) session.set_keyspace(ks) logging.info(f'Set keyspace successful !!!')
To create a Table in Cassandra within a Keyspace, execute the following code snippet:
def create_table(session, ks, table): logging.info(f'Checking for existence of table {table}') rows = session.execute("SELECT table_name FROM system_schema.tables WHERE keyspace_name='" + ks + "'") if table not in [row[0] for row in rows]: session.execute(""" CREATE TABLE %s ( isbn text, title text, year int, price float, PRIMARY KEY (isbn)) """ % table) logging.info(f'Create table successful !!!')
To insert a new row into a Table in Cassandra, execute the following code snippet:
def insert_row(session, table, isbn, title=None, year=0, price=0.0): logging.info(f'Inserting row in table {table} for key {isbn}') session.execute(""" INSERT INTO %s (isbn, title, year, price) VALUES ('%s', '%s', %d, %f) """ % (table, isbn, title, year, price)) logging.info(f'Insert into table successful !!!')
To query all the rows from a Table in Cassandra, execute the following code snippet:
def select_all_rows(session, table): logging.info(f'Querying from table {table}') rows = session.execute(""" SELECT * FROM %s """ % table) for row in rows: if row.year is None: logging.info(f'>>> {row.isbn}, {row.title}, null, null') else: logging.info(f'>>> {row.isbn}, {row.title}, {row.year}, {row.price:.02f}') logging.info(f'Query from table successful !!!')
To update a row from a Table in Cassandra for a given key, execute the following code snippet:
def update_row(session, table, isbn, title=None, year=0, price=0.0): logging.info(f'Updating row in table {table} for key {isbn}') session.execute(""" UPDATE %s SET price = %f, title = '%s', year = %d WHERE isbn = '%s' """ % (table, price, title, year, isbn)) logging.info(f'Update of table successful !!!')
To delete few columns from a Table in Cassandra for a given key, execute the following code snippet:
def delete_columns(session, table, isbn): logging.info(f'Deleting columns from table {table} for key {isbn}') session.execute(""" DELETE price, year FROM %s WHERE isbn = '%s'; """ % (table, isbn)) logging.info(f'Delete of columns from table successful !!!')
To clean up all the used resources and disconnect from Cassandra cluster, execute the following code snippet:
def clean_up(cluster, session, ks, table): logging.info(f'Ready to perform cleanup') session.execute("""DROP TABLE %s""" % table) session.execute("""DROP KEYSPACE %s""" % ks) session.shutdown() cluster.shutdown() logging.info(f'Cleanup successful !!!')
To test the CRUD operations in the Cassandra cluster, execute the following code snippet:
if __name__ == '__main__': c_cluster, c_session = get_cluster_session(CASSANDRA_HOST, CASSANDRA_PORT) set_keyspace(c_session, CASSANDRA_KS) create_table(c_session, CASSANDRA_KS, CASSANDRA_TABLE) insert_row(c_session, CASSANDRA_TABLE, isbn='ISBN-111') select_all_rows(c_session, CASSANDRA_TABLE) update_row(c_session, CASSANDRA_TABLE, isbn='ISBN-111', title='Cassandra Quick Notes', year=2023, price=2.99) select_all_rows(c_session, CASSANDRA_TABLE) insert_row(c_session, CASSANDRA_TABLE, isbn='ISBN-222', title='Cassandra Guide', year=2021, price=4.99) insert_row(c_session, CASSANDRA_TABLE, isbn='ISBN-333', title='Cassandra For Developers', year=2019, price=3.99) select_all_rows(c_session, CASSANDRA_TABLE) delete_columns(c_session, CASSANDRA_TABLE, isbn='ISBN-333') select_all_rows(c_session, CASSANDRA_TABLE) clean_up(c_cluster, c_session, CASSANDRA_KS, CASSANDRA_TABLE)
The following would be the typical output:
2023-11-30 11:53:18,914 - Connecting to 127.0.0.1 at port 9042 2023-11-30 11:53:18,934 - Connection successful !!! 2023-11-30 11:53:18,934 - Checking for existence of keyspace my_test_ks 2023-11-30 11:53:18,971 - Set keyspace successful !!! 2023-11-30 11:53:18,972 - Checking for existence of table book_catalog 2023-11-30 11:53:19,080 - Create table successful !!! 2023-11-30 11:53:19,080 - Inserting row in table book_catalog for key ISBN-111 2023-11-30 11:53:19,081 - Insert into table successful !!! 2023-11-30 11:53:19,081 - Querying from table book_catalog 2023-11-30 11:53:19,082 - >>> ISBN-111, None, 0, 0.00 2023-11-30 11:53:19,082 - Query from table successful !!! 2023-11-30 11:53:19,082 - Updating row in table book_catalog for key ISBN-111 2023-11-30 11:53:19,083 - Update of table successful !!! 2023-11-30 11:53:19,083 - Querying from table book_catalog 2023-11-30 11:53:19,083 - >>> ISBN-111, Cassandra Quick Notes, 2023, 2.99 2023-11-30 11:53:19,084 - Query from table successful !!! 2023-11-30 11:53:19,084 - Inserting row in table book_catalog for key ISBN-222 2023-11-30 11:53:19,084 - Insert into table successful !!! 2023-11-30 11:53:19,084 - Inserting row in table book_catalog for key ISBN-333 2023-11-30 11:53:19,085 - Insert into table successful !!! 2023-11-30 11:53:19,085 - Querying from table book_catalog 2023-11-30 11:53:19,086 - >>> ISBN-333, Cassandra For Developers, 2019, 3.99 2023-11-30 11:53:19,086 - >>> ISBN-111, Cassandra Quick Notes, 2023, 2.99 2023-11-30 11:53:19,086 - >>> ISBN-222, Cassandra Guide, 2021, 4.99 2023-11-30 11:53:19,086 - Query from table successful !!! 2023-11-30 11:53:19,086 - Deleting columns from table book_catalog for key ISBN-333 2023-11-30 11:53:19,086 - Delete of columns from table successful !!! 2023-11-30 11:53:19,086 - Querying from table book_catalog 2023-11-30 11:53:19,087 - >>> ISBN-333, Cassandra For Developers, null, null 2023-11-30 11:53:19,087 - >>> ISBN-111, Cassandra Quick Notes, 2023, 2.99 2023-11-30 11:53:19,087 - >>> ISBN-222, Cassandra Guide, 2021, 4.99 2023-11-30 11:53:19,087 - Query from table successful !!! 2023-11-30 11:53:19,087 - Ready to perform cleanup 2023-11-30 11:53:19,733 - Cleanup successful !!!
This wraps on how to work with Apache Cassandra using Python.
Hands-on with Cassandra using Spring Boot
To setup the Java directory structure for the demonstrations, execute the following commands:
$ cd $HOME
$ mkdir -p java/springboot/cassandra
$ cd $HOME/java/springboot/cassandra
$ mkdir -p src/main/java src/main/resources target
$ mkdir -p src/main/java/com/polarsparc/cassandra
$ mkdir -p src/main/java/com/polarsparc/cassandra/config
$ mkdir -p src/main/java/com/polarsparc/cassandra/model
$ mkdir -p src/main/java/com/polarsparc/cassandra/repository
$ mkdir -p src/main/java/com/polarsparc/cassandra/service src/main/java/com/polarsparc/cassandra/service/impl
For the Spring Boot based demonstration, we will leverage Maven to manage the build as well as the package dependencies.
The following is the Maven file pom.xml that is located in the directory $HOME/java/cassandra:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.polarsparc</groupId> <artifactId>Cassandra</artifactId> <version>1.0</version> <name>Cassandra</name> <description>Cassandra</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-cassandra</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
The following are the contents of the Spring Boot application properties file called application.properties , which defines the logging level and some Cassandra configuration options:
# # @Author: Bhaskar S # @Blog: https://www.polarsparc.com # @Date: 30 Nov 2023 # logging.level.root=INFO spring.cassandra.contact-points=127.0.0.1 spring.cassandra.port=9042 spring.cassandra.keyspace-name=my_test_ks spring.cassandra.schema-action=NONE
The property spring.cassandra.schema-action with a value of NONE means - don't create the Cassandra database on startup.
The following are the contents of the Java POJO BookCatalog.java which represents a row in the Cassandra database:
/* @Author: Bhaskar S @Blog: https://www.polarsparc.com @Date: 30 Nov 2023 */ package com.polarsparc.cassandra.model; import org.springframework.data.cassandra.core.mapping.Column; import org.springframework.data.cassandra.core.mapping.PrimaryKey; import org.springframework.data.cassandra.core.mapping.Table; @Table("book_catalog") public class BookCatalog { @PrimaryKey @Column private String isbn; @Column private String title; @Column private int year; @Column private double price; public BookCatalog() { this.isbn = null; this.title = null; this.year = 0; this.price = 0.0; } public BookCatalog(String isbn, String title, int year, double price) { this.isbn = isbn; this.title = title; this.year = year; this.price = price; } public BookCatalog(String isbn) { this(isbn, null, 0, 0.0); } public String getIsbn() { return isbn; } public void setIsbn(String isbn) { this.isbn = isbn; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return "BookCatalog{" + "isbn='" + isbn + '\'' + ", title='" + title + '\'' + ", year=" + year + ", price=" + price + '}'; } }
For any Spring Boot application that wants to interact with Cassandra, it needs a connection (session) to the cluster. The application.properties indicates the values for where to connect, which Keyspace to use and so on. That information needs to be translated into a configuration bean for Spring Boot to access, so that it can create the necessary session bean.
The following are the contents of the Spring Boot configuration Java bean CassandraConfig.java located in the directory src/main/java/com/polarsparc/cassandra/config:
package com.polarsparc.cassandra.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.data.cassandra.config.AbstractCassandraConfiguration; import org.springframework.data.cassandra.config.SchemaAction; import org.springframework.lang.NonNull; @Configuration public class CassandraConfig extends AbstractCassandraConfiguration { @Value("${spring.cassandra.keyspace-name}") private String keySpace; @Value("${spring.cassandra.contact-points}") private String contactPoints; @Value("${spring.cassandra.port}") private int port; @Value("${spring.cassandra.schema-action}") private String schemaAction; @Override @NonNull protected String getKeyspaceName() { return keySpace; } @Override @NonNull protected String getContactPoints() { return contactPoints; } @Override protected int getPort() { return port; } @Override @NonNull public SchemaAction getSchemaAction() { return SchemaAction.valueOf(schemaAction); } }
The following are the contents of the Java service interface called BookCatalogService.java which defines the various CRUD operations on the Cassandra database and is located in the directory src/main/java/com/polarsparc/cassandra/service:
/* @Author: Bhaskar S @Blog: https://www.polarsparc.com @Date: 30 Nov 2023 */ package com.polarsparc.cassandra.service; public interface BookCatalogService { void insertBookCatalog(String isbn, String title, int year, double price); void queryBookCatalogs(); void removeBookCatalogs(); void removePriceAndYear(String isbn); void updateBookCatalog(String isbn, String title, int year, double price); }
The following are the contents of the Java class called BookCatalogServiceImpl.java which implements the Java service interface BookCatalogService, and is located in the directory src/main/java/com/polarsparc/cassandra/service/impl:
/* @Author: Bhaskar S @Blog: https://www.polarsparc.com @Date: 30 Nov 2023 */ package com.polarsparc.cassandra.service.impl; import com.polarsparc.cassandra.model.BookCatalog; import com.polarsparc.cassandra.repository.BookCatalogRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.polarsparc.cassandra.service.BookCatalogService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.Optional; @Service public class BookCatalogServiceImpl implements BookCatalogService { private final static Logger LOGGER = LoggerFactory.getLogger(BookCatalogServiceImpl.class.getName()); private BookCatalogRepository repository; @Autowired public void setRepository(BookCatalogRepository repository) { this.repository = repository; } @Override public void insertBookCatalog(String isbn, String title, int year, double price) { BookCatalog bookCatalog = new BookCatalog(isbn, title, year, price); LOGGER.info(String.format("Inserting row for %s in book_catalog", isbn)); repository.insert(bookCatalog); } @Override public void queryBookCatalogs() { LOGGER.info(String.format("Count of rows in book_catalog: %d", repository.count())); LOGGER.info("Querying all rows in book_catalog"); repository.findAll().forEach(row -> LOGGER.info(row.toString())); } @Override public void removeBookCatalogs() { LOGGER.info("Removing all rows from book_catalog"); repository.deleteAll(); } @Override public void removePriceAndYear(String isbn) { LOGGER.info(String.format("Removing price and year for %s in book_catalog", isbn)); Optional<BookCatalog> bookCatalog = repository.findById(isbn); if (bookCatalog.isPresent()) { LOGGER.info(String.format("Found row for %s in book_catalog", isbn)); BookCatalog bc = bookCatalog.get(); bc.setPrice(0.0); bc.setYear(0); LOGGER.info(String.format("Updating row for %s in book_catalog", isbn)); repository.save(bc); } else { LOGGER.warn(String.format("No row for %s in book_catalog", isbn)); } } @Override public void updateBookCatalog(String isbn, String title, int year, double price) { LOGGER.info(String.format("Querying row for %s in book_catalog", isbn)); Optional<BookCatalog> bookCatalog = repository.findById(isbn); if (bookCatalog.isPresent()) { LOGGER.info(String.format("Found row for %s in book_catalog", isbn)); BookCatalog bc = bookCatalog.get(); bc.setTitle(title); bc.setPrice(price); bc.setYear(year); LOGGER.info(String.format("Updating row for %s in book_catalog", isbn)); repository.save(bc); } else { LOGGER.warn(String.format("No row for %s in book_catalog", isbn)); } } }
The following are the contents of the Spring Boot repository interface called BookCatalogRepository.java that defines all the CRUD operations on the Cassandra database and is located in the directory src/main/java/com/polarsparc/cassandra/repository:
/* @Author: Bhaskar S @Blog: https://www.polarsparc.com @Date: 30 Nov 2023 */ package com.polarsparc.cassandra.repository; import com.polarsparc.cassandra.model.BookCatalog; import org.springframework.data.cassandra.repository.CassandraRepository; public interface BookCatalogRepository extends CassandraRepository{}
Finally, the following are the contents of the Spring Boot application called CassandraApplication.java that performs all the CRUD operations on the Cassandra database:
/* @Author: Bhaskar S @Blog: https://www.polarsparc.com @Date: 30 Nov 2023 */ package com.polarsparc.cassandra; import com.polarsparc.cassandra.repository.BookCatalogRepository; import com.polarsparc.cassandra.service.BookCatalogService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories; @SpringBootApplication @EnableCassandraRepositories(basePackageClasses = BookCatalogRepository.class) public class CassandraApplication implements CommandLineRunner { private ConfigurableApplicationContext context; private BookCatalogService service; @Autowired public void setContext(ConfigurableApplicationContext context) { this.context = context; } @Autowired public void setService(BookCatalogService service) { this.service = service; } public static void main(String[] args) { SpringApplication.run(CassandraApplication.class, args); } @Override public void run(String... args) { service.insertBookCatalog("ISBN-111", null, 0, 0.0); service.queryBookCatalogs(); service.updateBookCatalog("ISBN-111", "Cassandra Quick Notes", 2023, 2.99); service.queryBookCatalogs(); service.insertBookCatalog("ISBN-222", "Cassandra Guide", 2021, 4.99); service.insertBookCatalog("ISBN-333", "Cassandra For Developers", 2019, 3.99); service.queryBookCatalogs(); service.removePriceAndYear("ISBN-333"); service.queryBookCatalogs(); service.removeBookCatalogs(); service.queryBookCatalogs(); System.exit(SpringApplication.exit(context)); } }
Launch the CQL command-line interface by executing the following command:
$ docker run -it --rm --name cas-client --network cassandra-db-net cassandra:5.0 cqlsh cas-node-1
The following will be the output:
WARNING: cqlsh was built against 5.0-alpha2, but this server is 5.0. All features may not work! Connected to Cassandra Cluster at cas-node-1:9042 [cqlsh 6.2.0 | Cassandra 5.0-alpha2 | CQL spec 3.4.7 | Native protocol v5] Use HELP for help. cqlsh>
On success, CQL will change the command prompt to "cqlsh>".
To create a Keyspace called my_test_ks, input the following command at the "cqlsh>" prompt:
cqlsh> CREATE KEYSPACE IF NOT EXISTS my_test_ks WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1};
There will be no output.
To use the Keyspace called my_test_ks, input the following command at the "cqlsh>" prompt:
cqlsh> USE my_test_ks;
There will be no output and the input prompt would change to "cqlsh:my_test_ks>".
To create a Table called book_catalog with a Primary Key, input the following command at the "cqlsh:my_test_ks>" prompt:
cqlsh:my_test_ks> CREATE TABLE IF NOT EXISTS book_catalog (isbn text, title text, year int, price double, PRIMARY KEY (isbn));
There will be no output.
Run the the Spring Boot application called CassandraApplication and following will be the typical output:
2023-12-01T13:46:47.121-05:00 INFO 24098 --- [ main] c.p.cassandra.CassandraApplication : Starting CassandraApplication using Java 21 with PID 24098 (/home/bswamina/MyProjects/Java/SpringBoot/Cassandra/target/classes started by bswamina in /home/bswamina/MyProjects/Java/SpringBoot/Cassandra) 2023-12-01T13:46:47.123-05:00 INFO 24098 --- [ main] c.p.cassandra.CassandraApplication : No active profile set, falling back to 1 default profile: "default" 2023-12-01T13:46:47.250-05:00 INFO 24098 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Cassandra repositories in DEFAULT mode. 2023-12-01T13:46:47.265-05:00 INFO 24098 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 13 ms. Found 1 Cassandra repository interface. 2023-12-01T13:46:47.294-05:00 INFO 24098 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Reactive Cassandra repositories in DEFAULT mode. 2023-12-01T13:46:47.298-05:00 INFO 24098 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 4 ms. Found 0 Reactive Cassandra repository interfaces. 2023-12-01T13:46:47.481-05:00 INFO 24098 --- [ main] c.d.o.d.i.core.DefaultMavenCoordinates : DataStax Java driver for Apache Cassandra(R) (com.datastax.oss:java-driver-core) version 4.17.0 2023-12-01T13:46:47.526-05:00 INFO 24098 --- [ main] c.d.o.d.i.c.c.CqlPrepareAsyncProcessor : Adding handler to invalidate cached prepared statements on type changes 2023-12-01T13:46:47.667-05:00 INFO 24098 --- [ s0-admin-0] c.d.oss.driver.internal.core.time.Clock : Using native clock for microsecond precision 2023-12-01T13:46:47.916-05:00 INFO 24098 --- [ main] c.d.o.d.i.c.c.CqlPrepareAsyncProcessor : Adding handler to invalidate cached prepared statements on type changes 2023-12-01T13:46:47.917-05:00 INFO 24098 --- [ s1-admin-0] c.d.oss.driver.internal.core.time.Clock : Using native clock for microsecond precision 2023-12-01T13:46:48.127-05:00 INFO 24098 --- [ main] c.p.cassandra.CassandraApplication : Started CassandraApplication in 1.161 seconds (process running for 1.427) 2023-12-01T13:46:48.128-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Inserting row for ISBN-111 in book_catalog 2023-12-01T13:46:48.175-05:00 WARN 24098 --- [ s1-io-3] c.d.o.d.i.core.cql.CqlRequestHandler : Query '[0 values] SELECT count(1) FROM book_catalog' generated server side warning(s): Aggregation query used without partition key 2023-12-01T13:46:48.176-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Count of rows in book_catalog: 1 2023-12-01T13:46:48.176-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Querying all rows in book_catalog 2023-12-01T13:46:48.185-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : BookCatalog{isbn='ISBN-111', title='null', year=0, price=0.0} 2023-12-01T13:46:48.185-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Querying row for ISBN-111 in book_catalog 2023-12-01T13:46:48.189-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Found row for ISBN-111 in book_catalog 2023-12-01T13:46:48.189-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Updating row for ISBN-111 in book_catalog 2023-12-01T13:46:48.193-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Count of rows in book_catalog: 1 2023-12-01T13:46:48.193-05:00 WARN 24098 --- [ s1-io-3] c.d.o.d.i.core.cql.CqlRequestHandler : Query '[0 values] SELECT count(1) FROM book_catalog' generated server side warning(s): Aggregation query used without partition key 2023-12-01T13:46:48.193-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Querying all rows in book_catalog 2023-12-01T13:46:48.194-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : BookCatalog{isbn='ISBN-111', title='Cassandra Quick Notes', year=2023, price=2.99} 2023-12-01T13:46:48.194-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Inserting row for ISBN-222 in book_catalog 2023-12-01T13:46:48.195-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Inserting row for ISBN-333 in book_catalog 2023-12-01T13:46:48.197-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Count of rows in book_catalog: 3 2023-12-01T13:46:48.197-05:00 WARN 24098 --- [ s1-io-3] c.d.o.d.i.core.cql.CqlRequestHandler : Query '[0 values] SELECT count(1) FROM book_catalog' generated server side warning(s): Aggregation query used without partition key 2023-12-01T13:46:48.197-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Querying all rows in book_catalog 2023-12-01T13:46:48.198-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : BookCatalog{isbn='ISBN-333', title='Cassandra For Developers', year=2019, price=3.99} 2023-12-01T13:46:48.198-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : BookCatalog{isbn='ISBN-111', title='Cassandra Quick Notes', year=2023, price=2.99} 2023-12-01T13:46:48.198-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : BookCatalog{isbn='ISBN-222', title='Cassandra Guide', year=2021, price=4.99} 2023-12-01T13:46:48.198-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Removing price and year for ISBN-333 in book_catalog 2023-12-01T13:46:48.199-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Found row for ISBN-333 in book_catalog 2023-12-01T13:46:48.199-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Updating row for ISBN-333 in book_catalog 2023-12-01T13:46:48.201-05:00 WARN 24098 --- [ s1-io-3] c.d.o.d.i.core.cql.CqlRequestHandler : Query '[0 values] SELECT count(1) FROM book_catalog' generated server side warning(s): Aggregation query used without partition key 2023-12-01T13:46:48.201-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Count of rows in book_catalog: 3 2023-12-01T13:46:48.201-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Querying all rows in book_catalog 2023-12-01T13:46:48.202-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : BookCatalog{isbn='ISBN-333', title='Cassandra For Developers', year=0, price=0.0} 2023-12-01T13:46:48.202-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : BookCatalog{isbn='ISBN-111', title='Cassandra Quick Notes', year=2023, price=2.99} 2023-12-01T13:46:48.202-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : BookCatalog{isbn='ISBN-222', title='Cassandra Guide', year=2021, price=4.99} 2023-12-01T13:46:48.202-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Removing all rows from book_catalog 2023-12-01T13:46:48.275-05:00 WARN 24098 --- [ s1-io-3] c.d.o.d.i.core.cql.CqlRequestHandler : Query '[0 values] SELECT count(1) FROM book_catalog' generated server side warning(s): Aggregation query used without partition key 2023-12-01T13:46:48.275-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Count of rows in book_catalog: 0 2023-12-01T13:46:48.275-05:00 INFO 24098 --- [ main] c.p.c.s.impl.BookCatalogServiceImpl : Querying all rows in book_catalog
To drop the entire table book_catalog, input the following command at the " cqlsh:my_test_ks>" prompt:
cqlsh:my_test_ks> DROP TABLE book_catalog;
There will be no output.
To drop the entire keyspace my_test_ks, input the following command at the " cqlsh:my_test_ks>" prompt:
cqlsh:my_test_ks> DROP KEYSPACE my_test_ks;
There will be no output.
To exit the CQL command-line interface, input the following command at the " cqlsh:my_test_ks>" prompt:
cqlsh:my_test_ks> exit;
There will be no output.
To stop the single-node Apache Cassandra cluster, execute the following command:
$ docker stop cas-node-1
This concludes the hands-on demonstration on how to work with Apache Cassandra via an application code using both Python and Spring Boot Java !!!
References