NATS Logo by Example

List Subjects for a Specific Stream in JetStream

All clients have a way to get the list of subjects for any given stream, except it’s not completely obvious how to do this. These examples will show you how to get the list of subjects.

CLI Go Python JavaScript Rust C# Java Ruby Elixir Crystal C
Jump to the output or the recording
$ nbe run jetstream/list-subjects/deno
View the source code or learn how to run this example yourself

Code

import {
    connect,
    nuid
} from "https://deno.land/x/nats@v1.28.0/src/mod.ts";


const servers = Deno.env.get("NATS_URL")?.split(",");


const nc = await connect({ servers });


const jsm = await nc.jetstreamManager();
const js = nc.jetstream();

Create a stream with a few random subjects

const plainSubj = `PLAIN_${nuid.next().substring(18)}`;
const gtSubj = `GT_${nuid.next().substring(18)}`;
const starSubj = `STAR_${nuid.next().substring(18)}`;
const name = `EVENTS_${nuid.next().substring(18)}`;


let si = await jsm.streams.add({
    name,
    subjects: [plainSubj, `${gtSubj}.>`, `${starSubj}.*`]
});


console.log(`Stream: ${si.config.name} has these subjects: '${si.config.subjects}'`)

Get stream info with StreamInfoRequestOptions

Get the subjects via the streams.info call. Since this is “state” there are no subjects in the state unless there are messages in the subject.

si = await jsm.streams.info(name, {subjects_filter: ">"});


const count = si.state.subjects
    ? Object.getOwnPropertyNames(si.state.subjects).length
    : 0;
console.log(`Before publishing any messages, there should be 0 subjects in the state: ${count}`)

console.log(Before publishing any messages, there are 0 subjects: ${si.state.num_subjects})

Publish a message

await js.publish(plainSubj)


si = await jsm.streams.info(name, {subjects_filter: ">"});
console.log("After publishing a message to a subject, it appears in state:")


if (si.state.subjects) {
    for (const [key, value] of Object.entries(si.state.subjects)) {
        console.log(`  subject '${key}' has ${value} message(s)`)
    }
}

Publish some more messages, this time against wildcard subjects

await js.publish(`${gtSubj}.A`, "gtA-1");
await js.publish(`${gtSubj}.A`, "gtA-2");
await js.publish(`${gtSubj}.A.B`, "gtAB-1");
await js.publish(`${gtSubj}.A.B`, "gtAB-2");
await js.publish(`${gtSubj}.A.B.C`, "gtABC");
await js.publish(`${gtSubj}.B.B.B`, "gtBBB");
await js.publish(`${starSubj}.1`, "star1-1");
await js.publish(`${starSubj}.1`, "star1-2");
await js.publish(`${starSubj}.2`, "star2");

Get all subjects

si = await jsm.streams.info(name, {subjects_filter: ">"});
console.log("Wildcard subjects show the actual subject, not the template.");


if (si.state.subjects) {
    for (const [key, value] of Object.entries(si.state.subjects)) {
        console.log(`  subject '${key}' has ${value} message(s)`)
    }
}

Subject Filtering

Instead of allSubjects, you can filter for a specific subject

si = await jsm.streams.info(name, {subjects_filter: `${gtSubj}.>`});
console.log(`Filtering the subject returns only matching entries ['${gtSubj}.>']`);


if (si.state.subjects) {
    for (const [key, value] of Object.entries(si.state.subjects)) {
        console.log(`  subject '${key}' has ${value} message(s)`)
    }
}


si = await jsm.streams.info(name, {subjects_filter: `${gtSubj}.A.>`});
console.log(`Filtering the subject returns only matching entries ['${gtSubj}.A>']`);


if (si.state.subjects) {
    for (const [key, value] of Object.entries(si.state.subjects)) {
        console.log(`  subject '${key}' has ${value} message(s)`)
    }
}


await nc.close();

Output

Stream: EVENTS_7Q3G has these subjects: 'PLAIN_7PKV,GT_7PR2.>,STAR_7PX9.*'
Before publishing any messages, there should be 0 subjects in the state: 0
After publishing a message to a subject, it appears in state:
  subject 'PLAIN_7PKV' has 1 message(s)
Wildcard subjects show the actual subject, not the template.
  subject 'GT_7PR2.A' has 2 message(s)
  subject 'GT_7PR2.A.B' has 2 message(s)
  subject 'GT_7PR2.A.B.C' has 1 message(s)
  subject 'GT_7PR2.B.B.B' has 1 message(s)
  subject 'PLAIN_7PKV' has 1 message(s)
  subject 'STAR_7PX9.1' has 2 message(s)
  subject 'STAR_7PX9.2' has 1 message(s)
Filtering the subject returns only matching entries ['GT_7PR2.>']
  subject 'GT_7PR2.A' has 2 message(s)
  subject 'GT_7PR2.A.B' has 2 message(s)
  subject 'GT_7PR2.A.B.C' has 1 message(s)
  subject 'GT_7PR2.B.B.B' has 1 message(s)
Filtering the subject returns only matching entries ['GT_7PR2.A>']
  subject 'GT_7PR2.A.B' has 2 message(s)
  subject 'GT_7PR2.A.B.C' has 1 message(s)

Recording

Note, playback is half speed to make it a bit easier to follow.