Python SQLAlchemy使用SQL索引时的自定义排序算法
可以在SQLAlchemy中编写带有索引的自定义排序函数吗?例如,SQLite允许将C级别的排序函数指定为 James Tauber提供了一些Unicode排序算法的实现,例如,它将所有“a”紧密地排序在一起,不管它们是否带有重音 这可能有用的其他示例包括不同的字母顺序(英语以外的语言)和数字值排序(排序Python SQLAlchemy使用SQL索引时的自定义排序算法,python,sql,indexing,sqlalchemy,collation,Python,Sql,Indexing,Sqlalchemy,Collation,可以在SQLAlchemy中编写带有索引的自定义排序函数吗?例如,SQLite允许将C级别的排序函数指定为 James Tauber提供了一些Unicode排序算法的实现,例如,它将所有“a”紧密地排序在一起,不管它们是否带有重音 这可能有用的其他示例包括不同的字母顺序(英语以外的语言)和数字值排序(排序10在9之后,而不是代码点顺序) 这在炼金术中可能吗?如果不支持,它是否由pysqlite3或MySQLdb模块支持,或者由python支持的任何其他SQL数据库模块支持 非常感谢您提供任何信息
10
在9
之后,而不是代码点顺序)
这在炼金术中可能吗?如果不支持,它是否由pysqlite3
或MySQLdb
模块支持,或者由python支持的任何其他SQL数据库模块支持
非常感谢您提供任何信息。下面是一个演示sqlite的unicode排序算法的示例:
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from pyuca import Collator
metadata = MetaData()
Base = declarative_base(metadata=metadata)
class Item(Base):
__tablename__ = 'Item'
id = Column(Integer, primary_key=True)
value = Column(String, nullable=False)
collator = Collator('allkeys.txt')
def collate_unicode(value1, value2):
return cmp(collator.sort_key(value1), collator.sort_key(value2))
engine = create_engine('sqlite://')
engine.raw_connection().create_collation('unicode', collate_unicode)
metadata.create_all(engine)
session = sessionmaker(engine)()
for word in [u"ĉambr", u"ĉar", u"car'", u"carin'", u"ĉe", u"ĉef'",
u"centjar'", u"centr'", u"cerb'", u"cert'", u"ĉes'", u"ceter'"]:
item = Item(value=word)
session.add(item)
session.commit()
for item in session.query(Item).order_by(collate(Item.value, 'unicode')):
print item.value
我对Denis Otkidach的答案做了一点修改,因此我将把我的更改添加为社区wiki,以防其他人感兴趣:
# -*- coding: utf-8 -*-
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy import types
from pyuca import Collator
class MyUnicode(types.TypeDecorator):
impl = types.Unicode
def get_col_spec(self):
# Return a new Unicode type sorted with
# the `mycollation` function
return 'Unicode COLLATE mycollation'
# Create the collator (sorting) function/instance
collator = Collator('allkeys.txt')
def mycollation(value1, value2):
if False:
# Use pyuca for sorting
return cmp(collator.sort_key(value1),
collator.sort_key(value2))
else:
# Normalize to lowercased combining characters for sorting
import unicodedata
return cmp(unicodedata.normalize('NFD', unicode(value1)).lower(),
unicodedata.normalize('NFD', unicode(value2)).lower())
# Create a new metadata/base/table
metadata = MetaData()
Base = declarative_base(metadata=metadata)
class Item(Base):
__tablename__ = 'CollatedTable'
id = Column(Integer, primary_key=True)
# (Note the `unique=True` in the next line so that an index
# is created, therefore stored in collated order for faster SELECTs)
value = Column(MyUnicode(), nullable=False, unique=True)
# Create a new database connection
engine = create_engine('sqlite://')
engine.echo = True # Print the SQL
engine.raw_connection().create_collation('mycollation', mycollation)
metadata.create_all(engine)
session = sessionmaker(engine)()
# Add some test data
for word in [u"ĉambr", u"ĉar", u"car'", u"carin'", u"ĉe", u"ĉef'",
u"centjar'", u"centr'", u"cerb'", u"cert'", u"ĉes'", u"ceter'",
u"zimble", u'bumble',
u'apple', u'ápple', u'ãpple',
u'đjango', u'django']:
item = Item(value=word)
session.add(item)
session.commit()
for item in session.query(Item).order_by(Item.value): # collate(Item.value, 'mycollation')
print item.value