How to create index about json object?

I want to implement an auction house function, where players can list equipment with different attributes. Players can filter and search based on the attributes of the equipment. Can I index the attributes of each equipment in the db?

Hello @hexun80149128,

Have a look at Nakama storage search.

There are examples of arrays here. Is there an example of map? @sesposito
I found SELECT(‘{“foo”:1, “bar”:2}’::JSONB?&array[‘foo’,‘bar’]); can work。 I wonder the
query code examaple.Thanks

I’m confused, your snippet looks like SQL which is not how the query syntax for the storage engine search works, can you elaborate on what the data you’ll be indexing looks like?

the json is like {“item”:{“config_id”:100029,“entry”:{“405”:333,“406”:509,“408”:95,“409”:90},“num”:1},“price”:5}. how can i write query to seach as entry has 405 key and 408 key?.thanks @sesposito

Assuming you’ve set up the index correctly, the query would look something like:

+value.item.entry.405>0 +value.item.entry.408>0

thanks。I will try

	if err := initializer.RegisterStorageIndex(logic.STORAGE_AUCTION_INDEX_NAME, logic.STORAGE_AUCTION_COLLECTION_NAME,
		logic.STORAGE_AUCTION_INDEX_KEY_NAME, []string{"item.entry"}, 1000, false); err != nil {
		logger.Error("Unable to RegisterStorageIndex: %v", err)
		return err

Is this right?and I want to know what the last parameter indexOnly true or false means respectively. Thanks


You can only index top-level keys. If you set it to just item it’ll index the whole object under that key, and the query should work.

1 Like

@sesposito Sorry to bother you again.I created an index and inserted a piece of data. But StorageIndexList does not return results. What is the reason。

	if err := initializer.RegisterStorageIndex("auctionIndex", "auction",
		"value", []string{"Item.Entry"}, 100000, false); err != nil {
		logger.Error("Unable to RegisterStorageIndex: %v", err)
		return err

and the log is
{"level":"info","ts":"2023-12-13T06:30:41.702Z","caller":"server/storage_index.go:630","msg":"Initialized storage engine index","configuration":{"collection":"auction","fields":["Item.Entry"],"index_only":false,"key":"value","max_entries":100000,"name":"auctionIndex"}} {"level":"info","ts":"2023-12-13T06:30:41.711Z","caller":"server/storage_index.go:325","msg":"Storage index loaded.","config":{"Name":"auctionIndex","MaxEntries":100000,"Collection":"auction","Key":"value","Fields":["Item.Entry"],"IndexOnly":false,"Index":{}},"elapsed_time_ms":2} I think the index is created success。
then insert data,such as

Then I write simple code to search.

	indexName := "auctionIndex"
	query := "*"
	limit := 10

	result, err := nk.StorageIndexList(ctx, "", indexName, query, limit)
	logger.Info("GetAuctionItemList", result, err)

but the log is "GetAuctionItemList%!(EXTRA *api.StorageObjects=, <nil>)"
It return nothing. thanks for help

another question @sesposito
A player lists items for auction. For example, if a player lists 2 items, I want to generate 2 pieces of data, but I found that StorageWrite can only write one piece of data per player. What is a good recommended method? Thanks

and query = “+value.Item.Entry.501>0 +value.Item.Entry.502>0” also return nothing

I think I wasn’t clear - []string{"Item.Entry"} nesting when setting the fields does not work, it has to be top level, so if your json contains a top level key called “item”, you need to set fields as []string{"Item"}

The key field (you’ve set it to “value”) should be the storage object key’s you wish to be considered for indexing, so with your current configuration, only the objects stored in Collection “auction” with Key “value” will be considered. You can also set the key param to “” so all the keys in that collection are indexed.

Hope this clarifies.

I want to know what the last parameter indexOnly true or false means respectively. Thanks

If indexOnly is false, then the lookups will be done in the index first, and then if there are matches the corresponding storage objects will be fetched from the DB and returned.

If indexOnly is true, then all the storage object data will be stored in the index when writes happen (uses more memory), and the lookups will never go through the DB at all.

after I change
initializer.RegisterStorageIndex("auctionIndex", "auction", "", []string{"Item"}, 100000, false)
query := "*" works. but
query = “+value.Item.Entry.500>0"
not works.
but the sql can find objects

after I change key to value,
initializer.RegisterStorageIndex("auctionIndex", "auction", "value", []string{"Item"}, 100000, false),
both query did not work.
@sesposito can you help me?thanks.

@sesposito and this also need your help.thanks.

@sesposito since I see Heroic Labs Documentation | Query Syntax sloved。need add:
“+value.Item.Entry.500:>0" will work.
another question, the query-syntax how to implement page turning function?thanks

Can I use jsnb such as {“userid”:xxx,“auctionid”:yyy} to store it under user_id? Any better recommendations? @sesposito thanks

I’m sorry I did not understand the question

@sesposito Since there are 1000 auction items,StorageIndexList max return 100 items,so I need query-syntax to return another items not 100 old。