Mastering MediaWiki Cargo Extension for Structured Data

What Cargo Brings to a MediaWiki Site

Imagine a wiki that can do more than just store pages—think of it as a lightweight database tucked inside your familiar editing interface. That’s what the Cargo extension promises. Instead of sprinkling raw tables across the site, Cargo stores rows in a hidden MySQL table, letting you query, sort, and display data with a syntax that feels almost like everyday wiki markup. In short, structured data meets the collaborative spirit of MediaWiki.

Why You Might Care

  • Need a catalog of books, movies, or research papers? Cargo can keep the list tidy and searchable.
  • Want to generate dynamic leaderboards from user‑contributed stats? One query, and the table updates automatically.
  • Fancy embedding charts without pulling in a separate analytics suite? Cargo’s output works nicely with extensions like Chart.js or Highcharts.

Even if you’ve never fiddled with SQL, Cargo’s parser functions feel like writing a template, not a script.

Getting Your Feet Wet

First off, Cargo isn’t a core part of MediaWiki— you have to install it. Grab the latest release from the official page, drop the folder into extensions/, and add the line

wfLoadExtension( 'Cargo' );

to LocalSettings.php. A quick clear‑cache and you’ll see a new “Special:CargoTables” in your toolbox.

Once Cargo's up, you’ll notice two things: a new syntax for defining tables (via templates) and a set of parser functions for pulling data out. Think of the first as setting up columns, the second as asking “What rows match this condition?”

Defining a Table: The Template Way

Most wikis create tables on the fly, but Cargo prefers a template that declares column types. Say you’re building a simple movie database. Create a template Template:Movie like so:

{{#cargo_declare:
| tables=Movies
| fields=Title=String,Year=Integer,Genre=String,Rating=Number
| format=wiki
}}
{{!}}'''Title'''{{!}}'''Year'''{{!}}'''Genre'''{{!}}'''Rating'''
{{!}}'''{{{Title}}}'''{{!}}'''{{{Year}}}'''{{!}}'''{{{Genre}}}'''{{!}}'''{{{Rating}}}'''

That block does two jobs. The #cargo_declare function tells Cargo: “Hey, make a table called Movies with these columns.” The rest of the template just shows a nice-looking wiki table for readers. Whenever you embed {{Movie|Title=Inception|Year=2010|Genre=Sci‑Fi|Rating=8.8}} on a page, Cargo silently writes a new row to the hidden database.

Column Types at a Glance

  • String – any text, best for names or titles.
  • Integer – whole numbers; useful for years or counts.
  • Number – decimals, perfect for ratings or percentages.
  • Coordinates – latitude/longitude pairs.
  • Date – ISO‑8601 dates, e.g., 2024-09-24.

Pick the right type; otherwise Cargo will try to coerce values and you might end up with “0” where you expected “N/A”.

Populating Data: Templates Meet Real Content

Now, you could manually embed the Movie template on dozens of pages, but that defeats the point of a structured system. A common pattern is to keep a “data page” for each entry, like Movie:Inception, and then include the template there.

{{Movie
| Title=Inception
| Year=2010
| Genre=Sci‑Fi
| Rating=8.8
}}

Every time you save that page, Cargo updates the Movies table automatically. No extra admin work, no separate import script. If you have an existing CSV, Cargo can ingest it too— just use the #cargo_import parser function on a hidden page:

{{#cargo_import:
| source=File:movies.csv
| format=csv
| table=Movies
}}

Just mind the column headers in the CSV; they must line up with the fields you declared earlier.

Querying the Data: From Simple Lists to Fancy Filters

The heart of Cargo is its query function. A minimal example that pulls every movie released after 2000 looks like this:

{{#cargo_query:
| tables=Movies
| fields=Title,Year,Rating
| where=Year>2000
| format=template
| template=MovieRow
}}

Here MovieRow is another tiny template you’d craft to format each result, perhaps as a table row or a bullet list. If you prefer raw wiki markup, swap format=template with format=wiki, and Cargo spits out a plain table.

Want to sort? Add order by=Rating DESC. Need a limit? Throw in limit=10. It’s as close to SQL as you’ll get without leaving the wiki editor.

Aggregates and Grouping

Cargo can do a little math. Suppose you want the average rating per genre:

{{#cargo_query:
| tables=Movies
| fields=Genre,AVG(Rating)=AvgRating
| group by=Genre
| format=wiki
}}

The result is a tidy two‑column table. Complex queries can even join tables, but that’s a rabbit hole best explored once you’re comfortable with basic queries.

Advanced Tricks: Linking, Images, and APIs

Because Cargo lives inside MediaWiki, you can cross‑reference pages effortlessly. Include a Page field in your #cargo_declare:

{{#cargo_declare:
| tables=Movies
| fields=Title=String,Year=Integer,Genre=String,Rating=Number,Page=Page
| format=wiki
}}

When you add | Page={{FULLPAGENAME}} to each data page, Cargo stores the exact wiki page name. Later, a query can pull that name and you can turn it into a link with the [[{{{Page}}}]] syntax inside your display template. It’s a neat way to let readers jump straight to a detailed article about a movie.

Images work similarly. Add a Cover=String field, store the filename, and in your output template use [[File:{{{Cover}}}|thumb|200px]]. The result is a thumbnail next to each row— no extra CSS required.

For developers who need the data outside the wiki, Cargo ships a JSON API endpoint. Hit something like /api.php?action=cargoquery&tables=Movies&fields=Title,Year,Rating&format=json and you’ll get a clean JSON array. Handy for external dashboards or mobile apps.

Performance Tips (Because Data Grows Fast)

Even though Cargo is designed for moderate datasets, a sprawling table can bog down queries. Here are some quick mitigations:

  1. Index Frequently Queried Columns: Add index=Year,Genre to the #cargo_declare line. Cargo creates underlying MySQL indexes, shaving seconds off large filter operations.
  2. Cache Results: Use the cache=86400 parameter in #cargo_query to store the output for a day. The wiki renders the cached HTML instead of re‑running the query every page view.
  3. Chunk Imports: When importing massive CSVs, break them into < 10 000‑row chunks. This prevents PHP timeouts and keeps the DB lock durations short.
  4. Avoid “Select *”: List only the fields you need. Pulling every column forces MySQL to read more data than necessary.

Lastly, keep an eye on the “Special:CargoTables” page. It shows row counts and can hint when a table is ballooning beyond expectations.

Common Pitfalls and How to Sidestep Them

New Cargo users often trip over a few quirks:

  • Missing field values – Parcel an empty string rather than leaving the parameter out; otherwise Cargo might treat the row as malformed.
  • Incorrect data types – Plugging a date into an Integer column yields zeros in queries. Double‑check your #cargo_declare definitions.
  • Template recursion – If your display template calls the same data template, you could end up in an infinite loop. Keep the logic one‑directional.
  • Excessive caching – Setting a long cache on constantly updated tables means visitors see stale numbers. Tailor the cache duration to the volatility of the source data.

Fixing these is usually a matter of a quick edit on the template or a tweak in the query parameters.

Where Cargo Fits in the Wider Wiki Ecosystem

There’s a smorgasbord of extensions that touch structured data: Semantic MediaWiki, DataValues, ExternalData. Cargo’s sweet spot is simplicity. You don’t need to learn an ontology language or install a heavyweight triple store. If your goal is “listable, filterable, and modestly searchable”, Cargo wins on low overhead.

That said, for large‑scale knowledge graphs or intricate inference rules, Semantic MediaWiki might still be the better companion. Cargo plays nicely alongside them, though— you can have a Semantic property on a page that pulls a value from a Cargo table, bridging the two worlds.

Final Thoughts (Without the Usual “Try It Now” Jargon)

Mastering Cargo isn’t about memorizing every flag; it’s about shaping your wiki’s data flow as naturally as you’d write prose. Declare your tables once, sprinkle the data template wherever the content lives, and let the query functions do the heavy lifting. With a few thoughtful indexes and a dash of caching, even a few thousand rows behave like a well‑tuned spreadsheet.

So the next time you find yourself wrestling with a static HTML table that never updates, remember there’s a hidden database waiting behind the scenes, obediently waiting for a #cargo_query to call it into action. And if you ever feel a bit lost, the official documentation is a treasure trove of examples— treat it like a cookbook, not a rulebook.

Subscribe to MediaWiki Tips and Tricks

Don’t miss out on the latest articles. Sign up now to get access to the library of members-only articles.
jamie@example.com
Subscribe