Get Bitmap from Redis in binary - node.js

I am working on a user activity feature in which I track the activity of a user everyday. I am thinking of using bitmap, so users who will be active on that day will be set to 1.
SETBIT users:2015:9:30 <userid> 1
I don't want to do GETBIT for each user. I want to retrieve the entire value in binary so I can iterate through it and find the active or inactive users.
I would like to know if this approach is correct and which node-module to use.

Bit arrays in Redis are stored as strings. To get the entire array, just do a regular GET and parse the bytes from the result.

To get the bitarray you should set return_buffers as true and then do a get operation on it this will give you a buffer object. Convert this buffer object to hex string and then iterate through it.
My solution
neoredis = require 'redis'
key = "h"
map =
"0":[]
"1":[3]
"2":[2]
"3":[2,3]
"4":[1]
"5":[1,3]
"6":[1,2]
"7":[1,2,3]
"8":[0]
"9":[0,3]
"a":[0,2]
"b":[0,2,3]
"c":[0,1]
"d":[0,1,3]
"e":[0,1,2]
"f":[0,1,2,3]
usersbufferobject = null
redis = neoredis.createClient(6379,'redis',{return_buffers:true})
redis.get key,(err,res)->
redis.quit()
if not err?
if res?
usersbufferobject = res.toString('hex')
users = []
offset = 0
arr = usersbufferobject.match(/.{1,2}/g)
for i in arr
for j in map[i[0]]
users.push(offset+j)
for j in map[i[1]]
users.push(offset+4+j)
offset+=8
console.log "Active Users",users
else
console.log "No users active"
process.exit()

Related

Get the label of a MathJax equation

How can I get the label of an equation? I'm attempting to reprocess an equation with a label, but I have to delete the label from MathJax.Extension["TeX/AMSmath"].labels first, for which the label must be known...
I know I can scan through the source text for the label MathJax.Hub.getAllJax("mathDiv")[0}.SourceElement().find("\label(") (...), but this seems needlessly complicated. Is there a better way?
There's no built-in API for this.
If you don't need to keep labels, then the reset in the comment above is probably the best way to go about it:
MathJax.Extension["TeX/AMSmath"].labels = {}
A quick and dirty way to get the IDs is to leverage the fact that they end up in the output. So you can just get all the IDs in the output, e.g.,
const math = MathJax.Hub.getAllJax()[0];
const nodesWithIds = document.getElementById(math.root.inputID).previousSibling.querySelectorAll('[id]');
const ids = [];
for (node of nodesWithIds) ids.push(node.id);
A cleaner and perhaps conceptually easier way would be to leverage MathML (which is essentially the internal format): the \label{} always ends up on an mlabeledtr. The trouble is that you'd have to re-parse that, e.g.,
const temp = document.createElement('span');
temp.innerHTML = math.root.toMathML();
const nodesWithIds = temp.querySelectorAll('mlabeledtr [id]');
const ids = [];
for (node of nodesWithIds) ids.push(node.id);
This will make sure the array only has relevant IDs in them (and the contents of the nodes should correspond to \label{}.
I suppose with helper libraries it might be easier to dive into the math.root object directly and look for IDs recursively (in its data key).

How to access individual values from an NSArray?

Trying to iterate through an array of values coming in from a push notification.
This is what the object in push notification object would look like:
"storyids": [12345, 12346, 12347, 12348]
At which, I can intercept this value in my ios app delegate, as such:
storyIds = aps.ObjectForKey(new NSString("storyids")) as NSArray;
But now I am having trouble iterating through this collection (which I want to essentially convert to a C# collection)
This is what I've tried:
for (nuint i = 0; i < storyIds.Count; i++)
{
var j = storyIds.ValueAt(i);
}
Which gives me a weird number and not the value at that particular index. I can't seem to find any method of NSArray to get the value from the array at a particular index.
You could use storyIds.GetItem<NSString> (0) or NSString.FromHandle (storyIds.ValueAt (0)).

How to retrieve all documents in couchdb database without causing out of memory

I have a coucdb database which contains about 200000 tweets, keys are tweet ID. I have a query which needs to retrieve all documents to look for some information. I'm using lightcouch to work with couchdb in a java web app. If I create a dbClient like this:
List<JsonObject>tweets = dbClient.view("_all_docs").query(JsonObject.class);
and then loop through tweets, for each JsonObject in tweets, use
JsonObject tweetJson = dbClient.find(JsonObject.class, tweet.get("id").toString().replaceAll("\"", ""));
to retrieve each tweet one by one it took extremely long time for 200000 documents. If I load all documents in one single query using includeDocs(true)
List<JsonObject>allTweets = dbClient.view("_all_docs").includeDocs(true).query(JsonObject.class);
it caused outofmemory exception since the number of documents are too large. So how can i deal with this problem? I'm thinking about using limit(5000) to retrieve 5000 documents for each time and loop through whole database, but I don't know how to write the loop to continue to retrieve the next 5000 after the first 5000 docs. One possible solution is using startKey and endKey but I'm confused how to use them when the key is tweet ID.
Use queryPage but make sure to use a String as the Key
See: https://github.com/lightcouch/LightCouch/issues/26#event-122327174
0.1.6 still seems to show this behaviour.
A workaround that I found for this goes something like this:
changes = DbClient.changes()
.since(null) // or... since(since) if you want an offset
.includeDocs(true);
int size = 1;
getCursor("0");
while (size > 0 ) {
ChangesResult resultSet = changes.limit(40000).getChanges();
List<ChangesResult.Row> rowList = resultSet.getResults();
for (ChangesResult.Row feed: rowList) {
<instantiate your object via gson>
.
.
.
}
getCursor(resultSet.getLastSeq());
size = rowList.size();
}

CouchDB "[Circular]" when writing to an array

In CouchDB, I am writing to an array and keep getting the message "[Circular]". I am using Node.js to create the data to be written like this.
Say I have an two email objects in the same document in CouchDB:
unverifiedEmail = [{"address":"john#example.com","dateAdded":"1389215329484"}]
verifiedEmail = []
Now in Node.js I do this before writing.
var oldData = readFromCouchDb();
var newData = oldData;
newData.verifiedEmail.unshift(newData.unverifiedEmail[0]);
writeToCouchDb(newData);
Then when I view the document in Futon I see this:
unverifiedEmail = [{"address":"john#example.com","dateAdded":"1389215329484"}]
verifiedEmail = "[Circular]"
What's going on here?
I found out the issue has to do with the depth of the way to set Javascript objects equal to each other.
To solve this, I used the following code in place of the unshift above:
newData.verifiedEmail.unshift(JSON.parse(JSON.stringify(newData.unverifiedEmail[0])));

How can I use a string in a table?

I need to use a string value as a table, in order to restore points to a player when they reconnect to a game server.
This string value is their profile ID, which never changes and I need to put data inside the string value (Kills, deaths, head shots) in order to effectively restore these points. I have had a quick look on the internet but I have not found much because I don't know what this specific thing is actually called.
To make it easier, here's what I have so far:
if (not Omega.Playertable) then
Omega.Playertable = {};
System.LogAlways("Set static record table on first connect");
end
local ID = g_gameRules.game:GetProfileId(player.id);
if (not Omega.Playertable.ID) then
table.insert(Omega.Playertable, ID);
Omega.Playertable.g_gameRules.game:GetProfileId(player.id).Kills=0;
Omega.Playertable.g_gameRules.game:GetProfileId(player.id).Deaths=0;
Omega.Playertable.g_gameRules.game:GetProfileId(player.id).Headshots=0;
else
local Kills=Omega.Playertable.g_gameRules.game:GetProfileId(player.id).Kills;
local Deaths=Omega.Playertable.g_gameRules.game:GetProfileId(player.id).Deaths;
local Headshots=Omega.Playertable.g_gameRules.game:GetProfileId(player.id).Headshots;
g_gameRules.game:SetSynchedEntityValue(playerId, 101, Kills);
g_gameRules.game:SetSynchedEntityValue(playerId, 100, Deaths);
g_gameRules.game:SetSynchedEntityValue(playerId, 102, Headshots);
end
As you can see, I've tried adding their ID into the table and adding info based on this. I cannot get the system to read the 'ID' value that I set before, so I tried adding the code that gets the ID instead, and it doesn't work. The ID is unique to each player so I cannot use a simple number system for this.
Could someone point out to me what I have done wrong here? If I manage to fix the problem, I will answer my own question on here so that it can be helpful to other users.
It seems to me that you are using the wrong table indexing syntax.
Indexing a table by a variables value in Lua is done with the [] syntax.
Furthermore, in Lua Foo.bar is syntactic sugar for Foo["bar"] both formats are interchangeable, but the . variant has limitations on which characters you can use with it. For example Foo["\n.*#%!"] is a valid table index, but you certainly can't write this: Foo.\n.*#%!
Also table.insert(t, v) inserts v at the end of the array part of the table. That means if you do this
foo = {};
foo.X = "Some value";
table.insert(foo, "X");
This is what you get
{
X = "Some value"
[1] = "X"
}
That means, if I apply this to the code you gave us, this is what you probably had in mind:
if (not Omega.Playertable) then
Omega.Playertable = {};
System.LogAlways("Set static record table on first connect");
end
local ID = g_gameRules.game:GetProfileId(player.id);
if (not Omega.Playertable[ID]) then
Omega.Playertable[ID] = {};
Omega.Playertable[ID].Kills=0;
Omega.Playertable[ID].Deaths=0;
Omega.Playertable[ID].Headshots=0;
else
local Kills = Omega.Playertable[ID].Kills;
local Deaths = Omega.Playertable[ID].Deaths;
local Headshots = Omega.Playertable[ID].Headshots;
g_gameRules.game:SetSynchedEntityValue(playerId, 101, Kills);
g_gameRules.game:SetSynchedEntityValue(playerId, 100, Deaths);
g_gameRules.game:SetSynchedEntityValue(playerId, 102, Headshots);
end
Try this:
s="35638846.12.34.45"
id,kills,deaths,headshots=s:match("(.-)%.(.-)%.(.-)%.(.-)$")
print(id,kills,deaths,headshots)
But note that these values are strings. If you're using them as numbers, use tonumber to convert them.

Resources