Используйте встроенную функцию cassandra `now()` для генерации TimeUUID с моделью в драйвере Python

У меня есть код как

import time

from uuid import uuid4

import cassandra
from cassandra.cqlengine.models import Model
from cassandra.cqlengine.query import BatchQuery
from cassandra.cqlengine import columns, connection
from cassandra.cqlengine.management import sync_table


class StudentModel(Model):
    __table_name__ = 'student'
    id = columns.UUID(primary_key=True, default=uuid4)
    created_timestamp = columns.TimeUUID(primary_key=True,
                                         clustering_order='DESC',
                                         default=cassandra.util.uuid_from_time(time.time()))
    name = columns.Text(required=True, default='')

class ClassRoomModel(Model):
    __table_name__ = 'class_room'
    id = columns.UUID(primary_key=True, default=uuid4)
    created_timestamp = columns.TimeUUID(primary_key=True,
                                         clustering_order='DESC',
                                         default=cassandra.util.uuid_from_time(time.time()))
    name = columns.Text(required=True, default='')

class StudentToClass(Model):
    __table_name__ = 'student_to_class_mapping'
    class_room_id = columns.UUID(primary_key=True)
    created_timestamp = \
        columns.TimeUUID(primary_key=True,
                         clustering_order='DESC',
                         default=cassandra.util.uuid_from_time(time.time()))
    student_id = columns.UUID()

class ClassToStudent(Model):
    __table_name__ = 'class_to_student_mapping'
    student_id = columns.UUID(primary_key=True)
    created_timestamp = \
        columns.TimeUUID(primary_key=True,
                         clustering_order='DESC',
                         default=cassandra.util.uuid_from_time(time.time()))
    class_room_id = columns.UUID()

if __name__ == '__main__':
    connection.setup(hosts=['localhost'],
                     default_keyspace='test')
    sync_table(StudentModel)
    sync_table(ClassRoomModel)
    sync_table(StudentToClass)
    sync_table(ClassToStudent)

    students = []
    for i in xrange(100):
        students.append(StudentModel.create(name='student' + str(i)))

    class_room = ClassRoomModel.create(name='class1')

    for student in students:
        print "Creating batch for: ", student.name
        with BatchQuery() as batch_query:
            ClassToStudent.batch(batch_query).create(
                student_id=student.id, class_room_id=class_room.id)
            StudentToClass.batch(batch_query).create(
                student_id=student.id, class_room_id=class_room.id)

Этот код работает нормально, и он также создал записи. Когда я проверяю количество записей, оно совпадает для 3 таблиц, но для test.student_to_class_mapping, должно быть 100, но это дает только 1,

cqlsh> select count(*) from test.student;

 count
-------
   100

(1 rows)
cqlsh> select count(*) from test.class_room ;

 count
-------
     1

(1 rows)
cqlsh> select count(*) from test.class_to_student_mapping;

 count
-------
   100

(1 rows)
cqlsh> select count(*) from test.student_to_class_mapping ;

 count
-------
     1

(1 rows)

Я нашел проблему, логика мудрая, его правильно, только проблема clusturing_key в test.student_to_class_mapping,

created_timestamp = \
    columns.TimeUUID(primary_key=True,
                     clustering_order='DESC',
                     default=cassandra.util.uuid_from_time(time.time()))

cassandra.util.uuid_from_time(time.time()) не может генерировать Unique UUID для каждой записи. я могу использовать uuid1 но я уже сталкиваюсь с проблемой uuid1,

Я знаю, мы можем использовать now() Я изменяю свой код на

from cassandra.query import BatchStatement, SimpleStatement
from cassandra.cqlengine import connection
...
...
    batch_query = BatchStatement()
    batch_query.add(
        SimpleStatement('INSERT INTO {0} '
            '("student_id", "created_timestamp", "class_room_id") '
            'VALUES ({1}, now(), {2})'.format(
                StudentToClass.column_family_name(),
                student.id, class_room.id)))
    batch_query.add(
        SimpleStatement('INSERT INTO {0} '
            '("student_id", "created_timestamp", "class_room_id") '
            'VALUES ({1}, now(), {2})'.format(
                ClassToStudent.column_family_name(),
                student.id, class_room.id)))   
    connection.session.execute(batch_query) 
...
... 

Теперь он работает нормально и создает все записи в соответствии с логикой.

Я хочу знать, есть ли способ использовать now() с моделью create метод?

1 ответ

Решение

Что случилось:

default = None
    the default value, can be a value or a callable (no args)

(из https://datastax.github.io/python-driver/api/cassandra/cqlengine/columns.html)

Ваша линия с

default=cassandra.util.uuid_from_time(time.time())

оценивается во время запуска и содержит одно значение как uuid. Попробуйте что-то вроде этого:

from uuid import uuid1,uuid4

class Comment(Model):
    photo_id = UUID(primary_key=True)
    comment_id = TimeUUID(primary_key=True, default=uuid1) # second primary key component is a clustering key
    comment = Text()

Нашел здесь. https://datastax.github.io/python-driver/api/cassandra/cqlengine/query.html

Еще одно (чисто личное) замечание - генерируйте явный uuid, как это часто нужно впоследствии;)

Другие вопросы по тегам