
Mastodon 和 Nostr:两种不同的社交产品,一样的去中心化愿景
概述:本文将分析和讲解Mastodon和Nostr这两个社交媒体平台,重点关注它们的产品应用和技术层面,以了解它们如何实现去中心化社交,并探讨它们在这方面的优势。我们将深入了解它们的架构设计和实现思路,并比较它们在用户体验、隐私保护、安全性等方面的差异。通过本文的分析和总结,读者将更好地了解这两个平台,以及它们在去中心化社交方面的贡献和发展。MastodonMastodon(长毛象)成立于2016年,是由Eugen Rochko创建的一个开源的微博客(microblog)平台,旨在为用户提供去中心化、隐私保护的社交体验。首先对涉及到的一些名词进行简单解释:联邦(federation):联邦是去中心化的一种形式。在联邦中,不是所有人共同使用一个中心服务,而是使用多个不限人数的服务器。ActivityPub:Mastodon使用一种标准化的、开放的协议来实现站点之间的互动,这种协议叫做ActivityPub。任何通过ActivityPub实现互联的软件都可以与Mastodon无缝通信,就像Mastodon站点之间的通信一样。实例(instance):每个人都可以在自己服务器上配置运行...

使用 The Graph 获取各大元宇宙项目交易信息
The graph 工作原理 Graph 根据subgraph描述(称为subgraph.graphq)学习什么以及如何索引以太坊数据。子图描述定义了subgraph感兴趣的智能合约,这些合约中要关注的事件,以及如何将事件数据映射到 The Graph 将存储在其数据库中的数据。该流程遵循以下步骤:去中心化应用程序通过智能合约上的交易将数据添加到以太坊。智能合约在处理交易时发出一个或多个事件。Graph Node 不断地扫描以太坊以寻找新的块以及它们可能包含的子图的数据。Graph Node 在这些块中为您的子图查找 Ethereum 事件并运行您提供的映射处理程序。映射是一个 WASM 模块,它创建或更新 Graph Node 存储的数据实体以响应以太坊事件。去中心化应用程序使用节点的GraphQL 端点查询 Graph 节点以获取从区块链索引的数据。Graph 节点反过来将 GraphQL 查询转换为对其底层数据存储的查询,以便利用存储的索引功能获取此数据。去中心化应用程序在丰富的 UI 中为最终用户显示这些数据,他们使用这些数据在以太坊上发布新交易。循环重复 (来自The ...
使用web3.py与智能合约交互
注:本篇文章交互用到的合约以及 infura 的创建与项目链接在本篇文章中提到一:安装二:使用1:通过infura链接来与以太坊合约交互输出为True话代表链接成功infura截图https://<your-provider-url>连接成功之后我们把本篇文章中的abi与部署的合约地址用到这里 abi文件(rent_nft_test.json)在 brownie_test/build/contracts 中 那么如何获取到该合约中发生得mint/transfer等信息from web3 import Web3 import json # 首先通过infura节点链接 w3=Web3(Web3.HTTPProvider('https://<your-provider-url>')) # 合约abi文件 with open('./brownie_test/build/contracts/ERC4907.json', 'r') as f: abi_contract = json.loads(f.read())['abi'] # 与infura节点链接成功后 指定address...



Mastodon 和 Nostr:两种不同的社交产品,一样的去中心化愿景
概述:本文将分析和讲解Mastodon和Nostr这两个社交媒体平台,重点关注它们的产品应用和技术层面,以了解它们如何实现去中心化社交,并探讨它们在这方面的优势。我们将深入了解它们的架构设计和实现思路,并比较它们在用户体验、隐私保护、安全性等方面的差异。通过本文的分析和总结,读者将更好地了解这两个平台,以及它们在去中心化社交方面的贡献和发展。MastodonMastodon(长毛象)成立于2016年,是由Eugen Rochko创建的一个开源的微博客(microblog)平台,旨在为用户提供去中心化、隐私保护的社交体验。首先对涉及到的一些名词进行简单解释:联邦(federation):联邦是去中心化的一种形式。在联邦中,不是所有人共同使用一个中心服务,而是使用多个不限人数的服务器。ActivityPub:Mastodon使用一种标准化的、开放的协议来实现站点之间的互动,这种协议叫做ActivityPub。任何通过ActivityPub实现互联的软件都可以与Mastodon无缝通信,就像Mastodon站点之间的通信一样。实例(instance):每个人都可以在自己服务器上配置运行...

使用 The Graph 获取各大元宇宙项目交易信息
The graph 工作原理 Graph 根据subgraph描述(称为subgraph.graphq)学习什么以及如何索引以太坊数据。子图描述定义了subgraph感兴趣的智能合约,这些合约中要关注的事件,以及如何将事件数据映射到 The Graph 将存储在其数据库中的数据。该流程遵循以下步骤:去中心化应用程序通过智能合约上的交易将数据添加到以太坊。智能合约在处理交易时发出一个或多个事件。Graph Node 不断地扫描以太坊以寻找新的块以及它们可能包含的子图的数据。Graph Node 在这些块中为您的子图查找 Ethereum 事件并运行您提供的映射处理程序。映射是一个 WASM 模块,它创建或更新 Graph Node 存储的数据实体以响应以太坊事件。去中心化应用程序使用节点的GraphQL 端点查询 Graph 节点以获取从区块链索引的数据。Graph 节点反过来将 GraphQL 查询转换为对其底层数据存储的查询,以便利用存储的索引功能获取此数据。去中心化应用程序在丰富的 UI 中为最终用户显示这些数据,他们使用这些数据在以太坊上发布新交易。循环重复 (来自The ...
使用web3.py与智能合约交互
注:本篇文章交互用到的合约以及 infura 的创建与项目链接在本篇文章中提到一:安装二:使用1:通过infura链接来与以太坊合约交互输出为True话代表链接成功infura截图https://<your-provider-url>连接成功之后我们把本篇文章中的abi与部署的合约地址用到这里 abi文件(rent_nft_test.json)在 brownie_test/build/contracts 中 那么如何获取到该合约中发生得mint/transfer等信息from web3 import Web3 import json # 首先通过infura节点链接 w3=Web3(Web3.HTTPProvider('https://<your-provider-url>')) # 合约abi文件 with open('./brownie_test/build/contracts/ERC4907.json', 'r') as f: abi_contract = json.loads(f.read())['abi'] # 与infura节点链接成功后 指定address...
Share Dialog
Share Dialog

Subscribe to Yooma

Subscribe to Yooma
<100 subscribers
<100 subscribers
注: 使用语言 python
Typesense将数据保存在磁盘当中,建立的索引保存内存中
Typesense是一个开源的、有容错能力的搜索引擎,针对实时(通常低于 50 毫秒)搜索即键入体验和开发人员生产力进行了优化。
Typesense做了一个对于其他搜索引擎的对比。(文档版,表格版)
索引数据速度以及资源占用:
对于220万份食谱(一份食谱相当于下文中提到的一个document)
在 Typesense 中进行索引时占用了大约 900MB 的 RAM(内存)
花了 3.6 分钟索引所有 220 万条记录
在具有 4 个 vCPU 的服务器上,Typesense 每秒能够处理104 个并发搜索查询,平均搜索处理时间为11毫秒。
RAM(内存)方面:如果数据量为 X MB大小,则需要占用2X-3XRAM(2-3倍数据量大小的占用)
如需深入了解可以查阅官方文档
centos:(如果您的系统不是centos可以在官方文档中找到对应的下载方法
curl -O https://dl.typesense.org/releases/0.23.1/typesense-server-0.23.1-1.x86_64.rpm
sudo yum install ./typesense-server-0.23.1-1.x86_64.rpm
如果从rpm包中安装typesense会自动启动服务,使用下面命令查看服务状态
sudo systemctl status typesense-server.service
Active 是 running 则代表已启动
配置文件位于/etc/typesense/typesense-server.ini
日志在/var/log/typesense/
数据目录在/var/lib/typesense/
日志目录和数据目录可以在配置文件中更改
curl http://localhost:8108/health
{"ok":true}
这是python版本的,如果需要其他版本可以在官网上查看
数据来源typesense官网 用于测试,如果自己有测试数据直接使用即可
cd /typesense_test # 任意目录
curl -O https://dl.typesense.org/datasets/books.jsonl.gz
gunzip books.jsonl.gz
import typesense
client = typesense.Client({
'nodes': [{
'host': 'localhost', # For Typesense Cloud use xxx.a1.typesense.net
'port': '8108', # For Typesense Cloud use 443
'protocol': 'http' # For Typesense Cloud use https
}],
'api_key': '<API_KEY>', # api-key 在 一-->2-->(2)中提到的配置文件中可以查看
'connection_timeout_seconds': 2
})
这样就可以和typesense交互了
以下代码都是在建立交互的基础上运行
在 typesense 中,一个 collection 相当于关系型数据库中的一张表
而 Documents 相当于表中的每条数据
创建一个 collection 时需要指定一些字段名和类型
(继续初始化代码,在初始化后:)
(如果使用自己数据需要根据数据的值类型来设置collection fields中的name type等)
books_schema = {
'name': 'books', # collection 的名字,对该集合操作都是根据该名字
'fields': [
{'name': 'title', 'type': 'string' },
{'name': 'authors', 'type': 'string[]', 'facet': True }, ###'facet': True facet字段被逐字索引
{'name': 'publication_year', 'type': 'int32', 'facet': True },
{'name': 'ratings_count', 'type': 'int32' },
{'name': 'average_rating', 'type': 'float' }
],
'default_sorting_field': 'ratings_count' # 在没有sort_by时检索结果默认以ratings_count字段排序
}
client.collections.create(books_schema)
######## 字段类型
type 描述
string 字符串值
string[] 字符串数组
int32 整数值高达 2,147,483,647
int32[] 数组int32
int64 大于 2,147,483,647 的整数值
int64[] 数组int64
float 浮点数/十进制数
float[] 浮点数/十进制数数组
bool true或者false
bool[] 布尔数组
geopoint 纬度和经度指定为[lat, lng]
geopoint[] 纬度和经度数组指定为[[lat1, lng1], [lat2, lng2]]
string* string自动将值转换为 a或的特殊类型string[]。 ###如果传入的值为1,那么会自动转化成 ‘1’
auto 自动尝试根据添加到集合中的文档推断数据类型的特殊类型。请参阅自动模式检测。
在创建完成后需要向里面添加数据,将刚刚下载好的测试数据添加到collection中
with open('/typesense_test/books.jsonl') as jsonl_file:
client.collections['books'].documents.import_(jsonl_file.read().encode('utf-8')) # books--collection中定义的name
或者自己有数据需要向里面添加
## 导入单条数据
document = {
'id': '124', ### 可以指定,也可以不指定,不指定的情况下就按自增的来
'company_name': 'Stark Industries', ### 以下字段是需要包含在collection中的字段,就相当于往数据表中添加数据,指定每个字段的值,如果collection中的有a字段在document中没有指定a字段的值,那么该条document在collection中没有a字段,在以后更新的时候可以再写入
'num_employees': 5215,
'country': 'USA'
}
client.collections['collection_name'].documents.create(document)
## 导入多条数据 数据集 在数据量比较大的情况下 这个方法效率很高
documents = [{
'id': '124',
'company_name': 'Stark Industries',
'num_employees': 5215,
'country': 'USA'
}]
# IMPORTANT: Be sure to increase connection_timeout_seconds to at least 5 minutes or more for imports,
# when instantiating the client
client.collections['collection'].documents.import_(documents, {'action': 'create'})
action
create 创建一个新的document,如果collection中有了相同的id,则创建失败
update 更新一个document,如果没有指定id,则更新失败
upsert 创建一个新document,或者在有该id的情况下更新该id的数据,需要发送整个document
emplace 创建一个新document,或者在有该id的情况下更新该id的数据,可以发送部分document或整个document
单个collection搜索
search_parameters = {
'q' : 'harry potter', # 搜索词
'query_by' : 'title', # 从title字段中检索
'sort_by' : 'ratings_count:desc' # 将搜索结果按ratings_count倒排
}
client.collections['books'].documents.search(search_parameters)
多个collection一起搜索
search_requests = {
'searches': [
{
'collection': 'books',
'query_by': 'title, authors' #
},
{
'collection': 'collection_name1',
'query_by': 'field1, field2, field3'
},
{
'collection': 'collection_name2',
'query_by': 'field1'
}
]
}
common_search_params = {
'q': 'xxxx' # 搜索词 相同的内容可以放在这里面,代表从每个collection中检索该词 如果query_by 都相同的情况下也可放在这里,把上面的去掉
}
client.multi_search.perform(search_requests, common_search_params)
对于搜索结果的处理以及排序方式还有疑问可以查阅官方文档
查看collection,返回collction结构(例如数据表的结构)
# 单个collection
client.collections['collection_name'].retrieve()
# 所有collection
client.collections.retrieve()
查看 document 数据
# 查看document
client.collections['collection_name'].documents['124'].retrieve() # 查看该collection中id为124的document的数据
更改collection结构
update_schema = {
'fields': [
{
'name' : 'num_employees',
'drop' : True ## 删除该字段
},
{
'name' : 'company_category',
'type' : 'string'
}
]
}
client.collections['collection_name'].update(update_schema)
更新document数据
document = {
'company_name': 'Stark Industries',
'num_employees': 5500
}
client.collections['collection_name'].documents['124'].update(document) ## 更新documentid为124的数据
删除 collection
client.collections['collection_name'].delete()
删除 document
client.collections['collection_name'].documents['124'].delete() # 删除 id为124的document
注:官方文档api
注: 使用语言 python
Typesense将数据保存在磁盘当中,建立的索引保存内存中
Typesense是一个开源的、有容错能力的搜索引擎,针对实时(通常低于 50 毫秒)搜索即键入体验和开发人员生产力进行了优化。
Typesense做了一个对于其他搜索引擎的对比。(文档版,表格版)
索引数据速度以及资源占用:
对于220万份食谱(一份食谱相当于下文中提到的一个document)
在 Typesense 中进行索引时占用了大约 900MB 的 RAM(内存)
花了 3.6 分钟索引所有 220 万条记录
在具有 4 个 vCPU 的服务器上,Typesense 每秒能够处理104 个并发搜索查询,平均搜索处理时间为11毫秒。
RAM(内存)方面:如果数据量为 X MB大小,则需要占用2X-3XRAM(2-3倍数据量大小的占用)
如需深入了解可以查阅官方文档
centos:(如果您的系统不是centos可以在官方文档中找到对应的下载方法
curl -O https://dl.typesense.org/releases/0.23.1/typesense-server-0.23.1-1.x86_64.rpm
sudo yum install ./typesense-server-0.23.1-1.x86_64.rpm
如果从rpm包中安装typesense会自动启动服务,使用下面命令查看服务状态
sudo systemctl status typesense-server.service
Active 是 running 则代表已启动
配置文件位于/etc/typesense/typesense-server.ini
日志在/var/log/typesense/
数据目录在/var/lib/typesense/
日志目录和数据目录可以在配置文件中更改
curl http://localhost:8108/health
{"ok":true}
这是python版本的,如果需要其他版本可以在官网上查看
数据来源typesense官网 用于测试,如果自己有测试数据直接使用即可
cd /typesense_test # 任意目录
curl -O https://dl.typesense.org/datasets/books.jsonl.gz
gunzip books.jsonl.gz
import typesense
client = typesense.Client({
'nodes': [{
'host': 'localhost', # For Typesense Cloud use xxx.a1.typesense.net
'port': '8108', # For Typesense Cloud use 443
'protocol': 'http' # For Typesense Cloud use https
}],
'api_key': '<API_KEY>', # api-key 在 一-->2-->(2)中提到的配置文件中可以查看
'connection_timeout_seconds': 2
})
这样就可以和typesense交互了
以下代码都是在建立交互的基础上运行
在 typesense 中,一个 collection 相当于关系型数据库中的一张表
而 Documents 相当于表中的每条数据
创建一个 collection 时需要指定一些字段名和类型
(继续初始化代码,在初始化后:)
(如果使用自己数据需要根据数据的值类型来设置collection fields中的name type等)
books_schema = {
'name': 'books', # collection 的名字,对该集合操作都是根据该名字
'fields': [
{'name': 'title', 'type': 'string' },
{'name': 'authors', 'type': 'string[]', 'facet': True }, ###'facet': True facet字段被逐字索引
{'name': 'publication_year', 'type': 'int32', 'facet': True },
{'name': 'ratings_count', 'type': 'int32' },
{'name': 'average_rating', 'type': 'float' }
],
'default_sorting_field': 'ratings_count' # 在没有sort_by时检索结果默认以ratings_count字段排序
}
client.collections.create(books_schema)
######## 字段类型
type 描述
string 字符串值
string[] 字符串数组
int32 整数值高达 2,147,483,647
int32[] 数组int32
int64 大于 2,147,483,647 的整数值
int64[] 数组int64
float 浮点数/十进制数
float[] 浮点数/十进制数数组
bool true或者false
bool[] 布尔数组
geopoint 纬度和经度指定为[lat, lng]
geopoint[] 纬度和经度数组指定为[[lat1, lng1], [lat2, lng2]]
string* string自动将值转换为 a或的特殊类型string[]。 ###如果传入的值为1,那么会自动转化成 ‘1’
auto 自动尝试根据添加到集合中的文档推断数据类型的特殊类型。请参阅自动模式检测。
在创建完成后需要向里面添加数据,将刚刚下载好的测试数据添加到collection中
with open('/typesense_test/books.jsonl') as jsonl_file:
client.collections['books'].documents.import_(jsonl_file.read().encode('utf-8')) # books--collection中定义的name
或者自己有数据需要向里面添加
## 导入单条数据
document = {
'id': '124', ### 可以指定,也可以不指定,不指定的情况下就按自增的来
'company_name': 'Stark Industries', ### 以下字段是需要包含在collection中的字段,就相当于往数据表中添加数据,指定每个字段的值,如果collection中的有a字段在document中没有指定a字段的值,那么该条document在collection中没有a字段,在以后更新的时候可以再写入
'num_employees': 5215,
'country': 'USA'
}
client.collections['collection_name'].documents.create(document)
## 导入多条数据 数据集 在数据量比较大的情况下 这个方法效率很高
documents = [{
'id': '124',
'company_name': 'Stark Industries',
'num_employees': 5215,
'country': 'USA'
}]
# IMPORTANT: Be sure to increase connection_timeout_seconds to at least 5 minutes or more for imports,
# when instantiating the client
client.collections['collection'].documents.import_(documents, {'action': 'create'})
action
create 创建一个新的document,如果collection中有了相同的id,则创建失败
update 更新一个document,如果没有指定id,则更新失败
upsert 创建一个新document,或者在有该id的情况下更新该id的数据,需要发送整个document
emplace 创建一个新document,或者在有该id的情况下更新该id的数据,可以发送部分document或整个document
单个collection搜索
search_parameters = {
'q' : 'harry potter', # 搜索词
'query_by' : 'title', # 从title字段中检索
'sort_by' : 'ratings_count:desc' # 将搜索结果按ratings_count倒排
}
client.collections['books'].documents.search(search_parameters)
多个collection一起搜索
search_requests = {
'searches': [
{
'collection': 'books',
'query_by': 'title, authors' #
},
{
'collection': 'collection_name1',
'query_by': 'field1, field2, field3'
},
{
'collection': 'collection_name2',
'query_by': 'field1'
}
]
}
common_search_params = {
'q': 'xxxx' # 搜索词 相同的内容可以放在这里面,代表从每个collection中检索该词 如果query_by 都相同的情况下也可放在这里,把上面的去掉
}
client.multi_search.perform(search_requests, common_search_params)
对于搜索结果的处理以及排序方式还有疑问可以查阅官方文档
查看collection,返回collction结构(例如数据表的结构)
# 单个collection
client.collections['collection_name'].retrieve()
# 所有collection
client.collections.retrieve()
查看 document 数据
# 查看document
client.collections['collection_name'].documents['124'].retrieve() # 查看该collection中id为124的document的数据
更改collection结构
update_schema = {
'fields': [
{
'name' : 'num_employees',
'drop' : True ## 删除该字段
},
{
'name' : 'company_category',
'type' : 'string'
}
]
}
client.collections['collection_name'].update(update_schema)
更新document数据
document = {
'company_name': 'Stark Industries',
'num_employees': 5500
}
client.collections['collection_name'].documents['124'].update(document) ## 更新documentid为124的数据
删除 collection
client.collections['collection_name'].delete()
删除 document
client.collections['collection_name'].documents['124'].delete() # 删除 id为124的document
注:官方文档api
No activity yet