Coder Social home page Coder Social logo

Querying Nested Slices? about bolthold HOT 21 CLOSED

mattgrayson avatar mattgrayson commented on June 18, 2024 3
Querying Nested Slices?

from bolthold.

Comments (21)

timshannon avatar timshannon commented on June 18, 2024 3

I'm going to re-open this to track adding some better slice query options. Off the top of my head I'm thinking:

  • Where("SliceField").ContainsAny(value1, value2, value3)
  • Where("SliceField").ContainsAll(value1, value2, value3)

Any other ideas?

from bolthold.

mattgrayson avatar mattgrayson commented on June 18, 2024 3

Either Contains or ContainsAll sounds reasonable. That said, while ContainsAll is more explicit in indicating what is being checked, it does read a bit awkwardly when only checking for a single value. So, I think you could make a case for all three variants (Contains, ContainsAll, and ContainsAny).

from bolthold.

timshannon avatar timshannon commented on June 18, 2024 3

#63

from bolthold.

timshannon avatar timshannon commented on June 18, 2024 2

SubQuery wouldn't be useful in this situation. Subquery would be useful if you wanted to run another separate query for each of the results of the MatchFuncQuery.

Using the comparer interface would remove the need for hte loop, but that same loop is essentially happening in the .In(...) query criteria, so go which whichever is clearer.

from bolthold.

timshannon avatar timshannon commented on June 18, 2024

from bolthold.

mattgrayson avatar mattgrayson commented on June 18, 2024

Makes sense - thanks!

from bolthold.

mh-cbon avatar mh-cbon commented on June 18, 2024

I was precisely looking for this functionality.

Its not so clear what ContainsAll means. is it like an hypothetic ContainsSome or is a somehow "stricter" equality ?

from bolthold.

timshannon avatar timshannon commented on June 18, 2024

@mh-cbon I was trying to match the strings package. They have .Contains and .ContainsAny. I thought ContainsAll was clearer than just Contains

val := struct {
    Set []string
}{
    Set: []string{"1", "2", "3"},
}
bh.Where("Set").ContainsAll("1", "3") //true
bh.Where("Set").ContainsAll("1", "3", "4") //false
bh.Where("Set").ContainsAny("1", "7", "4") //true

Maybe it'll be simpler and clearer to only have .Contains that accepts one value, and people can use and / or to do the same:

val := struct {
    Set []string
}{
    Set: []string{"1", "2", "3"},
}
bh.Where("Set").Contains("1").And("Set").Contains("3") //true
bh.Where("Set").Contains("1").And("Set").Contains("3").And("Set").Contains("4") //false
bh.Where("Set").Contains("1").Or(bh.Where("Set").Contains("7")).Or(bh.Where("Set").Contains("4")) //true

More verbose, but clearer, which is guess in the end is more like idiomatic Go. After typing all of that up, I'm leaning towards this 2nd option.

Thoughts?

from bolthold.

Kvaz1r avatar Kvaz1r commented on June 18, 2024

Why don't have both option? Contains for single parameter and ContainsAny{All} for several?

from bolthold.

timshannon avatar timshannon commented on June 18, 2024

I would expect having even more options would make things even less clear. The fact the @mh-cbon was confused that ContainsAll means the wording I chose was less than clear.

from bolthold.

mh-cbon avatar mh-cbon commented on June 18, 2024

second option is no-go in my opinion it just makes things harder.

First version is much better, it makes sense with insights about the design.

However, does the lib handle a strict Eq equality over basics slice types ? I mean does the And(f).Eq([]T{1,2,3}) works and returns true ? That was what bothered me about the {All}, at first i could not determine how it behaves in comparison to Eq.

from bolthold.

timshannon avatar timshannon commented on June 18, 2024

from bolthold.

timshannon avatar timshannon commented on June 18, 2024

Also, @mh-cbon what specifically is "harder". That you have to type more or that it's less clear?

from bolthold.

mh-cbon avatar mh-cbon commented on June 18, 2024

both. harder to read, harder to build. It does not look like a good api. the first version was unclear to me at first, but that is what documentation and examples are made for.

from bolthold.

timshannon avatar timshannon commented on June 18, 2024

Is ContainsEach("1", "2", "3") clearer than ContainsAll("1","2", "3")?

from bolthold.

mh-cbon avatar mh-cbon commented on June 18, 2024

I think ContainsAll / ContainsAny are perfect.

from bolthold.

timshannon avatar timshannon commented on June 18, 2024

FYI, when using Contains/All/Any on a value other than a slice, I plan on simply not matching instead of returning a error.

from bolthold.

timshannon avatar timshannon commented on June 18, 2024

Details are in the README:

https://github.com/timshannon/bolthold#slices-in-structs-and-queries

from bolthold.

muety avatar muety commented on June 18, 2024

What if the slice's values are not primitives, but structs again, whose fields I want to compare to?
For instance, assume the above example is modified like this:

type Tag struct {
    Id int,
    Name string
}

// [...]
ItemTest{
    Key:  1,
    ID:   32,
    Name: "pizza",
    Tags: []Tag{Tag{Id: 1, Name: "cheese"}, Tag{Id: 2, Name: "sausage"}},
}
// [...]

Probably I can use .MatchFunc() for this, but I'm not sure how. Could somebody please give me a little support?

from bolthold.

timshannon avatar timshannon commented on June 18, 2024

Yeah Match Func would work, or you could implement the Comparer interface on your Tag struct:

func (t Tag) Compare(other interface{}) (int, error) {
	if t.Id == other.(Tag).Id {
		return 0, nil
	}

	if t.Id < other.(Tag).Id {
		return -1, nil
	}
	return 1, nil
}

The code above assumes you want to compare based on Tag ID.

from bolthold.

muety avatar muety commented on June 18, 2024

Very cool, thanks! I achieved what I wanted with MatchFunc using the following code.

q.Where("Tags").MatchFunc(func(ra *bolthold.RecordAccess) (bool, error) {
	if field := ra.Field(); field != nil {
		for _, item := range field.([]*Tag) {
			if item.Id == "foo" {
				return true, nil
			}
		}
		return false, nil
	}
})

However, I was wondering if I could also use .SubQuery() instead of manually iterating the slice. Could you provide some minimal documentation for that?

from bolthold.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.