xzz2021
发布于 2024-11-05 / 4 阅读
0
0

edgeDB入门使用记录(一)

edgeDB入门使用记录(一)

概述: edgedb是一种新型的面向对象的数据库, 外表关联采用类似对象继承的方式(每张表都是一个类obj的set), 会自动隐式link, 每条数据都会自动创建uuid, 数据库采用迁移的模式, 查询语句, 命令语句更亲和于一般编程语法, 所以更加简洁方便! 同时: 前端可以直接发送请求url及查询体获得数据,无需后端服务!

需要注意的点: 1. 在 Edgedb 中,“无数据”会被显示为空集:{};2. ""(空字符串)实际上也是数据。 3. 注释使用符号#

  1. 安装好软件后,先执行初始化命令, 会自动创建一个数据库, 名称默认为edgedb; 找到default.esdl文件,配置定义数据库模块(类似创建数据库或表格)

    edgedb project init
    
  2. 改动数据库之后,可以使用命令进行执行, 类似创建快照(会自动检测对比上一版,生成迁移文件, 保存所有版本快照, 用于记录变动或方便回溯)

    edgedb migration create
    //  补充:  如果数据库type已有数据, 而迁移后有新增required字段,会导致异常
    //  解决方案: 1. 删除type表中没有此字段的所有数据,再进行迁移
    //          2. 如果不想删除,执行创建命令后会有提示, 给不含此字段的所有数据设一个默认值
    //   fill_expr> <std::str>{} 
    //   在{}括号中间输入需要设定的默认值
    //  补充,执行后会看不到列字段变化, 需要插入一条数据后才会更新
    //  fill_expr> 逃生舱函数 1. assert_exists 2. assert_single 3. type 	
    //  casts  (<bigint>.xp)
    
  3. 执行数据库更改, 自动找到最新生成的迁移文件, 根据文件内代码执行迁移, 避免误操作

    edgedb migrate
    
  4. 查看数据库

    edgedb list types
    
  5. 程序会自动创建一个强大的可视化web服务, 执行命令后会自动调用浏览器打开,类似在线的workbench

    edgedb ui
    
  6. 稍有不同的操作符

    := 用于声明,类似赋值; = 用于判断是否相等; != 用于判断是否不相等

  7. 插入数据, insert + 类名(表名) + {}

    //  一般赋值
    insert User {
    	name := "xzz"
    	pwd  := "123"
    }
    //  筛选 条件 插入 使用()包裹条件查询语句 
    insert Vampire {
      name := 'Count Dracula',
      places_visited := (select Place filter .name = 'Romania'),
      # .places_visited is the result of this select query.
    };
    
    
  8. 定义普通数组数据可以使用 array<str> , 但如果有外链关联, 可以使用 multi 链接其他对象

    type City {
      required name: str;
      modern_name: str;
    }
    // 普通数组
    type NPC {
    	required name: str;
    	places_visited: array<str>;
    }
    // 关联外表的数组数据
    type NPC {
    	required name: str;
    	multi places_visited: City 
    }
    
  9. 插入关联数据

    //  因为没有过滤筛选, 此处相当于把关联city的所有数据都进行链接
    insert NPC {
      name := 'Jonathan Harker',
      places_visited := City,
    };
    // 查看指定数据内部属性
    select NPC {
      name,
      places_visited: {
        name
      }
    };
    
  10. 定义标量类型: 每次只保存一个值, 如枚举值, 语句结尾必须加上; 作为结束

    scalar type Class extending enum<Rogue, Mystic, Merchant>;
    
  11. 定义抽象类, 抽象类只能被继承, 不能执行操作, 否则会抛出异常

    abstract type Person {
      required name: str;
      multi places_visited: City;
    }
    
  12. 转换数据类型, 使用 <> 进行类型声明

    select <int32>'9' + 9;
    // 可以连续转换, is 表示判断, 会返回boolean
    select <str><int64><str><int32>50 is str;
    
  13. 过滤数据, 关键词: filter

    // .name 是 Person.name 的缩写
    select Person {
      name,
      places_visited: {name},
    } filter .name = 'Emil Sinclair';
    
    
  14. 其他关键词

    1. like 区分大小写
    2. ilike 不区分
    3. % 匹配部分符合的内容类似模糊搜索; 如 like Bistr% 可以匹配到“Bistritz”,不能匹配“bistritz”
    4. [] 索引匹配 .name[0] = 'B' 匹配名称第一位是B的数据
    5. slice 返回切割的数据
  15. 数据约束, 关键词: constraint std::max_value(max: anytype)

    // max_value() 作为具体限制
    scalar type HumanAge extending int16 {
      constraint max_value(120);
    }
    // min(2,6,4,1) 获取其中最小值
    
  16. 删除数据, 关键词: delete , 如果数据有被引用, 会删除失败

    //  普通删除
    delete Country;
    // 需要查看 删除的数据
    select (delete Country) {
      name
    };
    
  17. 插入数据时, 希望只链接单条数据, 类似一对一关系映射, 关键词: assert_single(); detached用于明确指向的是原始对象, 而非正在创建的对象本身

    //  demo1
    insert NPC {
      name := 'Mina Murray',
      lover := assert_single(
        (
          select detached NPC
          filter .name = 'Jonathan Harker'
        )
      ),
      places_visited := (select City filter .name = 'London'),
    };
    
    //  demo2
    insert MinorVampire {
      name := 'Vampire Woman 1',
        master := assert_single(
        (select Vampire filter .name = 'Count Dracula')
      ),
    };
    
  18. 判断对应结果是否为空 {} , 关键词: exists

    select Person {
      name,
      is_single := not exists Person.lover,
    };
    
  19. 指定返回结果数量, 关键词: limit

    select Movie {*} limit 1 ;
    
  20. 时间类型:

    1. std::datetime 带日期时间时区的精确数据
    2. cal::local_datetime 不带时区的日期时间数据
    3. cal::local_time 只返回时间
    4. cal::local_date 只返回日期
    select <cal::local_time>('15:44:56');
    // 定义module,也即定义新的表
    type Time {
      required clock: str;
      property clock_time := <cal::local_time>.clock;
      property hour := .clock[0:2];   // 此处表示slice, 截取0到1两位
    }
    
  21. 条件判断: (result) if (condition) else

    type Time {
      required clock: str;
      property clock_time := <cal::local_time>.clock;
      property hour := .clock[0:2];
      property vampires_are := SleepState.Asleep if <int16>.hour > 7 and <int16>.hour < 19
            else SleepState.Awake;
    }
    
  22. 插入数据的同时查询结果, 优先执行()内的语句, 并且可以对数据进行computed

    select ( # Start a selection
      insert Time { # Put the insert inside it
        clock := '22:44:10'
      }
    ) # The bracket finishes the selection
      { # Now just choose the properties we want
        clock,
        hour,
        vampires_are,
        double_hour := <int16>.hour * 2
      };
    
  23. 查看type(表格)的相关信息, 关键词: describe

    // 一般信息
    describe type Time
    // 详细信息
    describe type Time as text
    
  24. 批量插入

    insert NPC {
      name := 'Jonathan Harker',
      places_visited := (
        select Place filter .name in {'Munich', 'Buda-Pesth', 'Bistritz'}
      )
    };
    
  25. 增量插入(更新), += 更接近原生js; 存量删除, -= 用于剔除某一条数据

    update NPC
    filter .name = 'Jonathan Harker'
    set {
      places_visited += (select Place filter .name = 'Slovakia')
    };
    
    
  26. 级联运算, ++ 类似字符串拼接

    select 'A character from the book:' ++ (select NPC.name) ++ ',who is not ';
    
  27. 当使用了link链接其他对象时, 清除数据会失败, 可以改为使用单个插入对象

    insert Vampire {
      name := 'Count Dracula',
      age := 800,
      slaves := {
        (insert MinorVampire {
          name := 'Vampire Woman 1',
        }),
        (insert MinorVampire {
          name := 'Vampire Woman 2',
        }),
        (insert MinorVampire {
          name := 'Vampire Woman 3',
        }),
      }
    };
    
  28. 想直接获取并返回json格式数据, <json>

    select <json> Person {*}
    
  29. 唯一值约束, 类似unique, constraint exclusive

    abstract type Person {
      required name: str { ## Add a block
          constraint exclusive;       ## and the constraint
      }
      multi places_visited: Place;
      lover: Person;
    }
    
    //  批量定义 约束 的值
    type BlogPost {
      title: str;
      author: User;
      constraint exclusive on ((.title, .author));
    }
    
  30. 如果对于被继承者, 希望允许重名,可以使用委托 delegated

    abstract type Person {
      required name: str {
        delegated constraint exclusive;
      }
      multi places_visited: Place;
      lover: Person;
      strength: int16;
    }
    
  31. 数组解包方法, array_unpack([3,6,8,4])

  32. 使用变量查询, 以$符号开头

    //  此处$n为任意名字的变量, 使用变量后会自动弹窗要求输入变量值
    select Person {  name } filter .name = <str>$n
    
  33. 多重继承, 以实现继承多个属性(与java里类的单继承相反)

    // 只有非抽象类才能继承(存疑)
    type Crewman extending HasNumber, Person {
    }
    
  34. 同一个type(表格)里插入自增数据, 可以使用 count(), 此函数会自动计算type表内数据数量

    with next_number := count(Crewman) + 1,
      insert Crewman {
      number := next_number
    };
    
  35. 使用序列, 类似mysql里的自增主键, sequence

    //  需要继承,否则删除本体若干数据后, 数字会在减少若干后的基础上增加
    scalar type TownspersonNumber extending sequence;
    type Townsperson extending Person {
      number: TownspersonNumber;
    }
    
  36. 使用 is 查询多类型数据, 翻译: 查询父类同时查询子类响应数据

    //  错误 因为 age 和 number 是 子类的属性
    select Person {
      name,
      age,
      number,
    };
    //  正确, 明确指定是哪一个 子类
    select Person {
      name,
      [is NPC].age,
      [is Crewman].number,
    };
    
  37. 超类型 supertype 子类型 subtypes

    //  此处 Person 是 子类型,  PC 是 超类型,  所以 会返回  true
    select Person {
        name,
        is_PC := Person is PC,
    };
    
  38. multi 与 数组的使用

    //  数组适合小型数据, 且适合需要索引的 场合
    type Castle extending Place {
      doors: array<int16>;
    }
    insert Castle {
      name := 'Castle Dracula',
      doors := [6, 19, 10],
    };
    
    //  multi  适合大型数据
    type Castle extending Place {
      multi doors: int16;
    }
    insert Castle {
      name := 'Castle Dracula',
      doors := {6, 19, 10},
    };
    
  39. 动态计算的link

    type Movie {
      required title: str;
      multi actors: Person;
    
      # returns all movies with same title
      multi same_title := (
        with t := .title
        select detached Movie filter .title = t
      )
    }
    
  40. 反向link

    type Movie {
      required title: str;
      multi actors: Person;
    }
    
    type Person {
      required name: str;
      multi acted_in := .<actors[is Movie];
    }
    
  41. 多态 (暂未理解)

    abstract type Content {
      required title: str;
    }
    
    type Movie extending Content {
      required release_year: int64;
    }
    
    type TVShow extending Content {
      required num_seasons: int64;
    }
    
    type Franchise {
      required name: str;
      multi entries: Content;
    }
    
  42. 给表中数据自动定义默认添加值, overload default

    type NPC extending Person {
      age: HumanAge;
      overloaded multi places_visited: Place {
        default := (select City filter .name = 'London');
      }
    }
    // 限定数据
    type NPC extending Person {
      overloaded age: int16 {
        constraint max_value(120);
      }
      overloaded multi places_visited: Place {
        default := (select City filter .name = 'London');
      }
    }
    
  43. 获取当前时间函数 datetime_current()

  44. 新增数据时, 自动插入当前时间 datetime_of_statement()

    abstract type Place {
      required name: str {
        delegated constraint exclusive;
      }
      modern_name: str;
      post_date: datetime {
        default := datetime_of_statement()
      }
    }
    
    
  45. 批量插入新数据, for in 合并数据: union

    // 批量插入
    for character_name in {'John Seward', 'Quincey Morris', 'Arthur Holmwood'}
    union (
      insert NPC {
        name := character_name,
        lovers := (select Person filter .name = 'Lucy Westenra'),
      }
    );
    //  循环
    for n in {1, 2, 3, 4, 5}
    union (
      insert Crewman {
        number := n,
        first_appearance := cal::to_local_date(1893, 7, 6),
        last_appearance := cal::to_local_date(1893, 7, 16),
      }
    );
    

评论