Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query into Point structs #380

Open
jpmeijers opened this issue May 26, 2023 · 2 comments
Open

Query into Point structs #380

jpmeijers opened this issue May 26, 2023 · 2 comments

Comments

@jpmeijers
Copy link

Proposal:
I'd like to have symmetry between writes and reads. When writing data into Infludb one would use a Point struct, with strict Tags, Fields, Measurement and Time values. When querying the data I want to see the returned results in this same format.

Current behavior:
The Point object when writing data is clear, and follows the basic concepts of Tags and Fields. When querying data the result is a pointer that contains a messy combination of tables and columns. Filtering these columns into Tags and Fields are tricky.

Desired behavior:
A query should ideally return the same format struct as what is written to the database. In other words I should be able to take a result and write it directly back to the database, without any data being lost. Updating a field would then be a write, update of the field value, and then a write.

Alternatives considered:
Describe other solutions or features you considered.

Use case:
Why is this important (helps with prioritizing requests)?

@jpmeijers
Copy link
Author

jpmeijers commented May 26, 2023

type ResultPoint struct {
	Tags  map[string]string
	Field string
	Time  time.Time
	Value interface{}
}

func QueryIntoPoints(query string) ([]ResultPoint, error) {
	var resultPoints []ResultPoint

	result, err := queryApi.Query(context.Background(), query)
	if err != nil {
		return nil, err
	}
	// check for an error
	if result.Err() != nil {
		return nil, result.Err()
	}

	var tagKeys []string
	ignoredColumns := []string{"result", "table"}

	// Iterate over query response
	for result.Next() {
		// Notice when group key has changed
		if result.TableChanged() {
			tagKeys = tagKeys[:0]
			for _, col := range result.TableMetadata().Columns() {
				if strings.HasPrefix(col.Name(), "_") {
					// don't use
				} else if slices.Contains(ignoredColumns, col.Name()) {
					// don't use
				} else {
					tagKeys = append(tagKeys, col.Name())
				}
			}
		}

		// Create a point and store time and value
		resultPoint := ResultPoint{
			Tags:  make(map[string]string, 0),
			Time:  result.Record().Time(),
			Value: result.Record().Value(),
		}

		// Set tags
		for _, tagKey := range tagKeys {
			tagValue, ok := result.Record().ValueByKey(tagKey).(string)
			if ok {
				resultPoint.Tags[tagKey] = tagValue
			}
		}

		// Set field
		field, ok := result.Record().ValueByKey("_field").(string)
		if ok {
			resultPoint.Field = field
		}

		resultPoints = append(resultPoints, resultPoint)
	}

	return resultPoints, err
}

This gives me something that resembles a Point struct.

@powersj
Copy link
Contributor

powersj commented May 30, 2023

Hi,

When sending data to InfluxDB, it needs to be in line protocol format. The point helper class essentially is a wrapper around that format. When querying data in InfluxDB v2, flux is used to query and return data in a format that is more easily used for additional querying, filtering, and parsing.

Having a function that would take the flux tables that are returned and converting that data into line protocol might be possible, assuming that all the field and tag data is present. We would accept a PR that provides this functionality, but it is not something we would prioritize as part of our own future development.

Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants