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

[][]Model, doubts about sorted returned array, using dataloader #683

Closed
frederikhors opened this issue Apr 18, 2019 · 2 comments
Closed

Comments

@frederikhors
Copy link
Collaborator

Question for newbies like me. Eventually, if that's okay with you, I can open a wiki page to collect all these FAQs for newbies.

I'm experimenting with gqlgen and dataloader pattern using dataloaden.

These are the models:

type School struct {
  ID   int
  Desc string
}

type Author struct {
  ID       int
  Name     string
  SchoolID int
}

type Book struct {
  ID       int
  Pages    int
  AuthorID int
}

This is the schema.graphql:

type School {
  id: ID
  desc: String
  authors: [Author]
}

type Author {
  id: ID
  name: String
  books: [Book]
}

type Book {
  id: ID
  pages: Int
  author: Author
}

I'm also using go-pg ORM (sqlboiler is planned) like this:

loaders.booksByAuthor = &BooksSliceLoader{
  wait:     1 * time.Millisecond,
  maxBatch: 100,
  fetch: func(keys []int) ([][]Book, []error) {
    var dbItems []Book
    keysIn := pg.In(keys)
    if err := DB.Model(&dbItems).Where("author_id in (?)", keysIn).OrderExpr("array_position(ARRAY[?]::int[], author_id::int)", keysIn).Select(); err != nil {
      return nil, []error{err}
    }
    items := make([][]Book, len(keys))
    for i, key := range keys {
      for _, dbItem := range dbItems {
        if dbItem.AuthorID == key {
          items[i] = append(items[i], dbItem)
        }
      }
    }
    return items, nil
  },
}

QUESTION

I was wondering if the below is an optimized way to re-order the [][]Book array coming from DB every time.

I'm asking about this code:

items := make([][]Book, len(keys))
for i, key := range keys {
  for _, dbItem := range dbItems {
    if dbItem.AuthorID == key {
      items[i] = append(items[i], dbItem)
    }
  }
}

Am I totally wrong?

Is this ok with the Golang Garbage Collector?

@Daavidaviid
Copy link

Hey,

I too am using gqlgen in a project with go-pg.
Personally, I do something like that :

ldrs.EmployeesByStore = &EmployeeSliceLoader{
			wait:     wait,
			maxBatch: 100,
			fetch: func(storeIDs []string) ([][]employee.Employee, []error) {
				var employees []employee.Employee

				employeesByStoreID := make([][]employee.Employee, len(storeIDs))
				errors := make([]error, len(storeIDs))

				err := database.DB.Model(&employee.Employee{}).
					Where("store_id in (?)", pg.In(storeIDs)).
					Select(&employees)

				for index, storeID := range storeIDs {
					for _, employee := range employees {
						if employee.StoreID == storeID {
							employeesByStoreID[index] = append(employeesByStoreID[index], employee)
						}
					}
				}

				if err != nil {
					errors := []error{err}
					return [][]employee.Employee{}, errors
				}

				return employeesByStoreID, errors
			},
		}

@vektah
Copy link
Collaborator

vektah commented Jun 26, 2019

#758 makes this a bit clearer

@vektah vektah closed this as completed Jun 26, 2019
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

3 participants