maxmind / mmdbwriter

Go library for writing MaxMind DB (mmdb) files
Apache License 2.0
116 stars 28 forks source link

How to insert custom region data with ipaddr #29

Closed intfish123 closed 2 years ago

intfish123 commented 2 years ago

I want to insert some ips into a new mmdb file. The code for inserting custom data:

writer, err := mmdbwriter.New(
    mmdbwriter.Options{
        DatabaseType: "GeoLite2-City",
        RecordSize:   24,
        Languages: []string{"en"},
    },
)
if err != nil {
    return err
}

nameId := 0
for i:=0; i<len(customData); i++ {
        record := mmdbtype.Map{}
        record["country"] = mmdbtype.Map{"geoname_id": mmdbtype.Uint64(nameId),"names":mmdbtype.Map{"en": mmdbtype.String(customData[i].Country)}}
        nameId++

        record["province"] = mmdbtype.Map{"geoname_id": mmdbtype.Uint64(nameId),"names":mmdbtype.Map{"en": mmdbtype.String(customData[i].Province)}}
        nameId++

        record["city"] = mmdbtype.Map{"geoname_id": mmdbtype.Uint64(nameId),"names":mmdbtype.Map{"en": mmdbtype.String(customData[i].City)}}
        nameId++

        record["county"] = mmdbtype.Map{"geoname_id": mmdbtype.Uint64(nameId),"names":mmdbtype.Map{"en": mmdbtype.String(customData[i].County)}}
        nameId++

        tmpIp := net.ParseIP(customData[i].ipVal)
        writer.Insert(&net.IPNet{IP: tmpIp, Mask: tmpIp.DefaultMask()}, record)
}
fh, err := os.Create("out/out.mmdb")
if err != nil {
    log.Fatal(err)
}
_, err = writer.WriteTo(fh)
if err != nil {
    log.Fatal(err)
}

Then I search ip for testing:

city, err := geoip2Reader.City(net.ParseIP(ipStr))
    if err == nil {
        marshal, _ := json.Marshal(city)
        zap.S().Info(string(marshal))
    }

The result of searching is not correct. Am I doing something wrong?

oschwald commented 2 years ago

There is no field in GeoIP2 City called province. That should be replaced with subdivisions, which is an array of objects. See, e.g., this.

intfish123 commented 2 years ago

I rewrote my code like this, But it still doesn't work, you can try it:

writer, err := mmdbwriter.New(
    mmdbwriter.Options{
        DatabaseType: "GeoLite2-City",
            RecordSize: 24,
            IPVersion: 4,
            IncludeReservedNetworks: true,
            Languages: []string{"zh-CN"},
    },
)
if err != nil {
    return err
}

nameId := 0
for i:=0; i<len(customData); i++ {
    record := mmdbtype.Map{}
    record["continent"] = mmdbtype.Map{
        "geoname_id": mmdbtype.Uint64(nameId),
        "code": mmdbtype.String(""),
        "names":mmdbtype.Map{"zh-CN": mmdbtype.String("")},
    }
    nameId++

    record["country"] = mmdbtype.Map{
        "geoname_id": mmdbtype.Uint64(nameId),
        "iso_code": mmdbtype.String(""),
        "names":mmdbtype.Map{"zh-CN": mmdbtype.String(customData[i].Country)},
    }
    nameId++

    record["subdivisions"] = mmdbtype.Slice{
        mmdbtype.Map{
            "geoname_id": mmdbtype.Uint64(nameId),
            "iso_code": mmdbtype.String(""),
            "names":mmdbtype.Map{"zh-CN": mmdbtype.String(customData[i].Province)},
      },
    }
    nameId++

    record["city"] = mmdbtype.Map{
        "geoname_id": mmdbtype.Uint64(nameId),
        "names":mmdbtype.Map{"zh-CN": mmdbtype.String(customData[i].City)},
    }
    nameId++

    record["county"] = mmdbtype.Map{
        "geoname_id": mmdbtype.Uint64(nameId),
        "names":mmdbtype.Map{"zh-CN": mmdbtype.String(customData[i].County)},
    }
    nameId++

    record["location"] = mmdbtype.Map{
        "accuracy_radius": mmdbtype.Uint16(0),
        "latitude": mmdbtype.Float64(0),
        "longitude": mmdbtype.Float64(0),
        "metro_code": mmdbtype.Uint64(0),
        "time_zone": mmdbtype.String(""),
    }
    nameId++

    record["postal"] = mmdbtype.Map{
        "code": mmdbtype.String(""),
    }
    nameId++

    record["registered_country"] = mmdbtype.Map{
        "geoname_id": mmdbtype.Uint64(nameId),
        "is_in_european_union": mmdbtype.Bool(false),
        "iso_code": mmdbtype.String(""),
        "names": mmdbtype.Map{"zh-CN": mmdbtype.String("")},
    }
    nameId++

    record["represented_country"] = mmdbtype.Map{
        "geoname_id": mmdbtype.Uint64(nameId),
        "is_in_european_union": mmdbtype.Bool(false),
        "iso_code": mmdbtype.String(""),
        "type": mmdbtype.String(""),
        "names": mmdbtype.Map{"zh-CN": mmdbtype.String("")},
    }
    nameId++
    nameId++

    tmpIp := net.ParseIP(customData[i].ipVal)
    writer.Insert(&net.IPNet{IP: tmpIp, Mask: tmpIp.DefaultMask()}, record)
}
fh, err := os.Create("out/out.mmdb")
if err != nil {
    log.Fatal(err)
}
_, err = dbWriter.WriteTo(fh)
if err != nil {
    log.Fatal(err)
}