Exchange从Neo4j导入Nebula,数据缺失属性

  • nebula 版本:v2.0.0
  • 部署方式(分布式 / 单机 / Docker / DBaaS):docker
  • 硬件信息
    • SSD
    • i5, 8GB
  • Exchange: v2.0.0
  • 导入数据会丢失属性

操作是,无论我是单独导入还是和其他种类的实体一起导入数据,person的name,gender等信息都无法插入进去,也没有报错信息,因为这些点只是部分属性为 __NULL__ ,其他都是正常的。也不是所有的vertex属性都缺失,也有部分vertex数据是完整的。边的数据也基本完整。

这个是person的tag的配置

 {
        name: person
        server: "bolt://127.0.0.1:7687"
        user: neo4j
        password: neo4j
        encryption: false
        type: {
            source: neo4j
            sink: client
        }
        fields       : [registeredPersonId, virtualId, merchantId, name, image, gender, contact, address]
        nebula.fields: [registeredPersonId, virtualId, merchantId, name, image, gender, contact, address]
        vertex: personId
        partition: 10
        batch: 200
        check_point_path: "file:///tmp/nebula-exchange/dev/vertex/person"
        exec: "match (n:Person) return n.personId as personId, n.registeredPersonId as registeredPersonId, n.virtualId as virtualId, n.merchantId as merchantId, n.name as name, n.image as image, n.gender as gender, n.contact as contact, n.address as address order by id(n)"
    }

所有属性都是string类型

导入结果是,merchantId和virtualId会正确导入进去,但是其他属性都会缺失。

源数据中name和gender对应的部分数据是不是空的

确实存在部分name和gender的数据为空

那这部分空数据导入完成后,如果对应的属性没有设置默认值的话,查询到的数据就会是_NULL_

但是我觉得,应该是没有该属性的数据是空,而不是所有数据的这个属性都是空,现在的表现就是所有person的name,gender都为空。

在我修改了scheme增加了默认值为""之后,依旧为__NULL__,但是正常用console插入的时候默认值是没问题的

通过出发bug打出的log,发现确实插入语句里面,那几个字段都被设置成了null。

然后我修改了一下neo4j的查询语句,设置了过滤掉所有name为空的数据,log里面,name就都不为__NULL__了,但是gender依然为__NULL__。

所以我猜测exchange在处理这部分数据时,如果该字段有为空的数据那么所有数据的该字段就都被设置为__NULL__了。也就是说如果person里面,有name为__NULL__那么所有person的name就都没了……

好的,我这边测试一下

在处理数据时没有对数据进行置空设置的,源数据字段的值是什么就直接拼接成ngql语句的,不对数据做处理(转义除外)。 gender为_NULL_ 是指所有的gender都是_NULL_么,Exchange对于有数据的字段没有做空类型转换的。 你可以把所有insert语句都打出来看下

:sweat_smile:今天不是__NULL__了,而是 null 了,不过现象跟之前是一样的,如果100条数据里面有部分数据name为null的,那么插入的log就都是

INSERT VERTEX person(rid,vid,mid,name) VALUES
 "6fe483b4-a3d0-11ea-a5e7-9a2bc6bd0790": (null, be0e06a6-678a-4cc5-890a-09a49ed0e61e, "1", null),
 "1d4e1797-a230-11ea-b54d-22f5d22dac93": (null, ef6d0fac-9ea1-47b4-9b24-e999889a07c7, "1", null) 

这样的数据(总共测试数据大概4w条),加上 n.name is not null 的判断条件之后,log就都正常了。

并且也不是所有字段都是这个情况,vid其实也是有部分数据为null的,但是这个字段就可以正常的不为null的字段正常有值,没有该字段的就为null;而且数据量少的时候比如几条,也是正常的:

 INSERT VERTEX test(name,gender,age,career) VALUES
 "1": ("1", female, 18, "student"),
 "2": ("2", male, 18, "student"), 
"3": ("3", female, 18, "student"), 
"4": ("4", male, null, null), 
"5": ("5", female, null, null), 
"6": ("6", male, null, null)

:joy: 这个数据咋还会变。
你用那个exec语句查一下,是不是对应的源数据中就是空值, 因为exchange导入时是将数据拼接成ngql语句,直接把源数据拼接到ngql语句中不做处理的。

:rofl:数据源确实不是空值,如果数据源为空值的话,加上 n.name is not null 之后应该会报 count() <= 0 的错了,所以我现在只能根据字段分别插入为空不为空的数据了

你那边可以debug看下 从neo4j读出来的数据内容是什么

那请问,怎么debug exchange啊 :blush:

而且,奇怪的是,如果我加上 n.registeredPersonId is not null 的过滤条件之后,log里面打出来的日志就是正常数据的日志,如果没加,就是所有数据的 registeredPersonId 和 name就都为null。

数据源确定没有变而且没有问题……而且我还写了个小demo里面只有7条数据就没有这个问题……

在你的编译器中给Exchange主类配置参数: -c property.conf (注意配置文件中要有spark.master这项配置)
然后加断点就可以debug Exchange了。

我又来了,这次是有了新的进展,在千辛万苦加上了断点之后,发现,其实从neo4j传过来的时候,在ServerBaseReader.scala里面,字段是有数据的

断点是在153行部分,这个数据是直接match return的数据,就是会出现bug的那种情况,说明数据源确实没问题……

然后紧接着是在Exchange.scala加断点的时候注意到处理space(正常)和person(不正常)的时候的问题:

space:

person:

name等字段的类型直接就变成null

问题应该出在ServerBaseReader.scala:146的地方

      val schema =
          if (result.hasNext)
            StructType(
              fields
                .map(k => (k, result.peek().get(k).`type`()))
                .map(keyType => CypherTypes.field(keyType)))
          else new StructType()

这段是利用返回的数据的第一条数据的类型转化成schema,但如果获取的数据类型为NULL,那么该字段就会被置为NULL,所以就会导致这个partition中所有数据的这个字段都是NULL即使数据原本不是NULL

3 个赞

这个地方是拿数据来获取Neo4j中的数据Schema,其实在导入Nebula时是不关注源数据schema的,可以将其转换为StringType。欢迎来贡献个pr :+1:

如果数据中只有string类型数据这么做是可以的,但是其他vertex的数据中还会有int类型数据,就会因为数据类型原因报错 :joy:

你说的vertex的数据是int类型只是数据本身,在生成DataFrame时是没有类型在的,指定为StringType的话 int数据也会作为StringType存储于DataFrame中的。 2.0的Exchange在将源数据转为NebulaGraph ngql语句时是不关注数据在DataFrame中的数据类型的,只关注NebulaGraph的数据类型。

PR来了,你用这个导入试下:fix neo4j's data type by Nicole00 · Pull Request #62 · vesoft-inc/nebula-spark-utils · GitHub

浙ICP备20010487号