Skip to content

Instantly share code, notes, and snippets.

@dashaun
Last active March 29, 2021 21:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dashaun/24cdc44181ae36888ea05e980e3ff4c5 to your computer and use it in GitHub Desktop.
Save dashaun/24cdc44181ae36888ea05e980e3ff4c5 to your computer and use it in GitHub Desktop.
version: "2"
services:
tweets-search:
image: abhirockzz/redisearch-tweets-search
ports:
- 80:80
environment:
- REDIS_HOST=<azure redis host name>
- REDIS_PASSWORD=<azure redis access key>
- REDISEARCH_INDEX_NAME=tweets-index
tweets-indexer:
image: abhirockzz/redisearch-tweets-consumer
environment:
- TWITTER_CONSUMER_KEY=<twitter api consumer key>
- TWITTER_CONSUMER_SECRET_KEY=<twitter api consumer secret>
- TWITTER_ACCESS_TOKEN=<twitter api access token>
- TWITTER_ACCESS_SECRET_TOKEN=<twitter api access secret>
- REDIS_HOST=<azure redis host name>
- REDIS_PASSWORD=<azure redis access key>
- REDISEARCH_INDEX_NAME=tweets-index
docker login azure
docker context create aci aci-context
docker context use aci-context
HTTP/1.1 200 OK
Page-Size: 10
Search-Hits: 12
Date: Mon, 25 Jan 2021 13:21:52 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
//JSON array of documents (omitted)
curl -i "$REDISEARCH_API_BASE_URL?q=*&offset_limit=0,100"
offset_limit=0,100 will return up to 100 documents ( limit ) starting with the first one ( offset = 0).
curl -i "$REDISEARCH_API_BASE_URL?q=@source:iphone"
curl -i "$REDISEARCH_API_BASE_URL?q=@location:india&fields=user,text"
curl -i "$REDISEARCH_API_BASE_URL?q=@user:jo*"
bash curl -i $REDISEARCH_API_BASE_URL?q=@location:India @source:android
curl -i "$REDISEARCH_API_BASE_URL?q=@hashtags:\{potus|cov*\}"
curl -i "$REDISEARCH_API_BASE_URL?q=@hashtags:{biden} @created:[1611556920000000000 1711556930000000000]"
curl -i "$REDISEARCH_API_BASE_URL?q=*&fields=coordinates"
curl -i "$REDISEARCH_API_BASE_URL?q=@coordinates:[-122.41 37.77 10 km]"
docker compose down -p azure-redisearch-app
git clone https://github.com/abhirockzz/redisearch-tweet-analysis
cd redisearch-tweet-analysis
config := oauth1.NewConfig(GetEnvOrFail(consumerKeyEnvVar), GetEnvOrFail(consumerSecretKeyEnvVar))
token := oauth1.NewToken(GetEnvOrFail(accessTokenEnvVar), GetEnvOrFail(accessSecretEnvVar))
httpClient := config.Client(oauth1.NoContext, token)
client := twitter.NewClient(httpClient)
demux := twitter.NewSwitchDemux()
demux.Tweet = func(tweet *twitter.Tweet) {
if !tweet.PossiblySensitive {
go index.AddData(tweetToMap(tweet))
time.Sleep(3 * time.Second)
}
}
go func() {
for tweet := range stream.Messages {
demux.Handle(tweet)
}
}()
host := GetEnvOrFail(redisHost)
password := GetEnvOrFail(redisPassword)
indexName = GetEnvOrFail(indexNameEnvVar)
pool = &redis.Pool{Dial: func() (redis.Conn, error) {
return redis.Dial("tcp", host, redis.DialPassword(password), redis.DialUseTLS(true), redis.DialTLSConfig(&tls.Config{MinVersion: tls}
}
rsClient := redisearch.NewClientFromPool(pool, indexName)
err := rsClient.DropIndex(true)
schema := redisearch.NewSchema(redisearch.DefaultOptions).
AddField(redisearch.NewTextFieldOptions("id", redisearch.TextFieldOptions{})).
AddField(redisearch.NewTextFieldOptions("user", redisearch.TextFieldOptions{})).
AddField(redisearch.NewTextFieldOptions("text", redisearch.TextFieldOptions{})).
AddField(redisearch.NewTextFieldOptions("source", redisearch.TextFieldOptions{})).
//tags are comma-separated by default
AddField(redisearch.NewTagFieldOptions("hashtags", redisearch.TagFieldOptions{})).
AddField(redisearch.NewTextFieldOptions("location", redisearch.TextFieldOptions{})).
AddField(redisearch.NewNumericFieldOptions("created", redisearch.NumericFieldOptions{Sortable: true})).
AddField(redisearch.NewGeoFieldOptions("coordinates", redisearch.GeoFieldOptions{}))
indexDefinition := redisearch.NewIndexDefinition().AddPrefix(indexDefinitionHashPrefix)
err = rsClient.CreateIndexWithIndexDefinition(schema, indexDefinition)
func AddData(tweetData map[string]interface{}) {
conn := pool.Get()
hashName := fmt.Sprintf("tweet:%s", tweetData["id"])
val := redis.Args{hashName}.AddFlat(tweetData)
_, err := conn.Do("HSET", val...)
}
qParams, err := url.ParseQuery(req.URL.RawQuery)
if err != nil {
log.Println("invalid query params")
http.Error(rw, err.Error(), http.StatusBadRequest)
return
}
searchQuery := qParams.Get(queryParamQuery)
query := redisearch.NewQuery(searchQuery)
http://localhost:8080/search?q=@source:Web&fields=user,source&offset_limit=5,100
fields := qParams.Get(queryParamFields)
offsetAndLimit := qParams.Get(queryParamOffsetLimit)
docs, total, err := rsClient.Search(query)
response := []map[string]interface{}{}
for _, doc := range docs {
response = append(response, doc.Properties)
}
rw.Header().Add(responseHeaderSearchHits, strconv.Itoa(total))
err = json.NewEncoder(rw).Encode(response)
docker compose up -p azure-redisearch-app
[+] Running 1/3
⠿ Group azure-redisearch-app Created 8.3s ⠸ tweets-search Creating 6.3s ⠸ tweets-indexer Creating 6.3s
docker logs azure-redisearch-app_tweets-indexer
docker logs azure-redisearch-app_tweets-search
docker ps
//output
CONTAINER ID IMAGE COMMAND STATUS PORTS azure-redisearch-app_tweets-search abhirockzz/redisearch-tweets-search Running 20.197.96.54:80->80/tcazure-redisearch-app_tweets-indexer abhirockzz/redisearch-tweets-consumer Running
id - this is a the Tweet ID ( TEXT attribute)
user - the is the screen name ( TEXT attribute)
text - tweet contents ( TEXT attribute)
source - tweet source e.g. Twitter for Android, Twitter Web App, Twitter for iPhone ( TEXT attribute)
hashtags - hashtags (if any) in the tweet (available in CSV format as a TAG attribute)
location - tweet location (if available). this is a user defined location (not the exact location per se)
created - timestamp (epoch) of the tweet. this is NUMERIC field and can be used for range queries
coordinates - geographic location (longitude, latitude) if made available by the client ( GEO attribute)
export REDISEARCH_API_BASE_URL=<for example, http://20.197.96.54:80/search>
curl -i $REDISEARCH_API_BASE_URL?q=*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment