Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/365.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 平面文件NoSQL解决方案_Python_Sql_Database_Sqlite_Nosql - Fatal编程技术网

Python 平面文件NoSQL解决方案

Python 平面文件NoSQL解决方案,python,sql,database,sqlite,nosql,Python,Sql,Database,Sqlite,Nosql,对于小型项目,SQLite(或类似)是否有一种内置方式来保持SQL/NoSQL的最佳性能,即: 将存储在类似SQLite的(平面)文件中(没有客户机/服务器方案,没有要安装的服务器;更准确地说:除了pip安装之外,没有其他要安装的东西) 可以将行存储为dict,而不必为每一行设置公共结构,如NoSQL数据库 支持简单查询 例如: db = NoSQLite('test.db') db.addrow({'name': 'john doe', 'balance': 1000, 'data': [

对于小型项目,SQLite(或类似)是否有一种内置方式来保持SQL/NoSQL的最佳性能,即:

  • 存储在类似SQLite的(平面)文件中(没有客户机/服务器方案,没有要安装的服务器;更准确地说:除了
    pip安装之外,没有其他要安装的东西)
  • 可以将行存储为
    dict
    ,而不必为每一行设置公共结构,如NoSQL数据库
  • 支持简单查询
例如:

db = NoSQLite('test.db')
db.addrow({'name': 'john doe', 'balance': 1000, 'data': [1, 73.23, 18]})
db.addrow({'name': 'alice', 'balance': 2000, 'email': 'a@b.com'})
for row in db.find('balance > 1500'):
    print(row)

# {'id': 'f565a9fd3a', 'name': 'alice', 'balance': 2000, 'email': 'a@b.com'}   # id was auto-generated
注意:多年来,我一直惊讶于SQLite在几行代码中可以实现多少有趣的功能,这就是为什么我想问,我在这里描述的内容是否可以通过仅使用几个SQLite核心功能而在SQLite中实现


PS:可能看起来像一个解决方案,但实际上它只是一个持久的键/值存储,没有查询/
find
函数;另外(BerkeleyDB for Python)看起来已弃用,没有类似API的查询功能。

可以使用扩展查询存储在列中的JSON数据,是:

sqlite> CREATE TABLE test(data TEXT);
sqlite> INSERT INTO test VALUES ('{"name":"john doe","balance":1000,"data":[1,73.23,18]}');
sqlite> INSERT INTO test VALUES ('{"name":"alice","balance":2000,"email":"a@b.com"}');
sqlite> SELECT * FROM test WHERE json_extract(data, '$.balance') > 1500;
data
--------------------------------------------------
{"name":"alice","balance":2000,"email":"a@b.com"}

如果要经常查询同一字段,可以通过在表达式上添加索引来提高效率:

CREATE INDEX test_idx_balance ON test(json_extract(data, '$.balance'));
将在上述查询中使用该索引,而不是扫描每一行。

SQLite
  • JSON1
    extension和
    json\u extract
    (参见公认答案)。例如:

    import sqlite3, json  # tested with precompiled Windows binaries from https://www.sqlite.org/download.html (sqlite3.dll copied in C:\Python37\DLLs)
    
    class sqlitenosql:
        def __init__(self, f):
            self.db = sqlite3.connect(f)
            self.db.execute('CREATE TABLE test(data TEXT);')
    
        def close(self):
            self.db.commit()
            self.db.close()
    
        def addrow(self, d):
            self.db.execute("INSERT INTO test VALUES (?);", (json.dumps(d),))
    
        def find(self, query):
            for k, v in query.items():
                if isinstance(v, str):
                    query[k] = f"'{v}'"
            q = ' AND '.join(f" json_extract(data, '$.{k}') = {v}" for k, v in query.items())
            for r in self.db.execute(f"SELECT * FROM test WHERE {q}"):
                yield r[0]
    
    db = sqlitenosql(':memory:')
    db.addrow({'name': 'john', 'balance': 1000, 'data': [1, 73.23, 18], 'abc': 'hello'})
    db.addrow({'name': 'alice', 'balance': 2000, 'email': 'a@b.com'})
    db.addrow({'name': 'bob', 'balance': 1000})
    db.addrow({'name': 'richard', 'balance': 1000, 'abc': 'hello'})
    for r in db.find({'balance': 1000, 'abc': 'hello'}):
        print(r)
    # {"name": "john", "balance": 1000, "data": [1, 73.23, 18], "abc": "hello"}
    # {"name": "richard", "balance": 1000, "abc": "hello"}    
    db.close()
    
  • 如和中所述 与:

    key=一个ID

    value=我们要存储的dict,例如,
    {'name':'alice','balance':2000,'email':'a@b.com“}

  • 进一步阅读SQLite与JSON的结合使用:

蒂尼德布 看起来是个不错的解决方案:

>>> from tinydb import TinyDB, Query
>>> db = TinyDB('path/to/db.json')
>>> User = Query()
>>> db.insert({'name': 'John', 'age': 22})
>>> db.search(User.name == 'John')
[{'name': 'John', 'age': 22}]
但是,文档中提到,如果我们需要:

  • 从多个进程或线程进行访问
  • 为表创建索引
  • HTTP服务器
  • 管理表或类似表之间的关系
  • 酸保证
所以这是一个半解:)

奥赫解决方案
似乎也很有趣:

哇,很好的解决方案!然后我猜,它会在整个数据库中循环执行
find('name=“john doe”')
?我想是这样的,因为SQLite必须提取所有行来测试名称是否匹配,对吗?@Basj您可能可以使用,但我没有尝试过。否则,是的,它必须查看每一行-注意,我没有说这样做是个好主意,只是说它可以做到。:)好的,表达式上的索引将与
json\u extract
()一起使用。谢谢!在使用
CREATE index test_idx_balance ON test(json_extract(data,'$.balance'))创建索引之后,您是否可以提供一个示例,说明如何执行查询