Corpus research

Four Vocabularies in One Field: A Metadata Census of 160 Million PRC Judgment Records

The first query anyone runs against a newly delivered corpus is a GROUP BY. How many civil cases, how many criminal, how many first instance, how many on appeal. The query returns in a second, the numbers look reasonable, and they go straight into a scoping deck.

We ran that query against our own index of PRC judgment records, and then spent a morning establishing what the answer actually meant. The short version is that the corpus carries at least four mutually incompatible vocabularies inside a single field, that the two most common ways of writing "civil matter" never co-occur in the same acquisition batch, and that the proportion of the corpus which is first-instance litigation is either 36.76% or 52.43% depending on how you decode one undocumented integer.

None of this is exotic. It is what happens to any large body of structured Chinese judgment data assembled over years from a public record that changed its own export conventions repeatedly. We are publishing the measurements because the failure mode is silent: every one of these fields returns a clean, plausible, well-formed number, and several of those numbers are wrong in ways that a schema document will never reveal.

A note on units, stated once. Every figure on this page counts records, not cases. A single dispute can produce several records — a judgment, a ruling, an enforcement order — and redundancy is not evenly distributed. Where we say "160 million" we mean 160,291,678 rows in an index, and nothing about how many distinct disputes those rows represent.

What was measured, and how to re-run it

One index, read on 26 August 2026: 160,291,678 records. Six categorical fields, each aggregated over the whole corpus with no filter, plus cross-tabulations against the acquisition-batch identifier the index happens to carry. The queries are ordinary Elasticsearch terms aggregations, and the only discipline that matters is setting track_total_hits to true — without it the reported total silently caps at ten thousand and every percentage you derive is nonsense.

POST /judgments/_search
{"size":0,"track_total_hits":true,
 "aggs":{"p":{"terms":{"field":"procedure","size":40,"missing":"__MISSING__"}}}}

That is the whole method. The missing parameter matters as much as the aggregation: a field can be absent, or it can be present and hold an empty string, and those are different populations that most tools collapse into one.

The completeness table

Before the vocabulary problem, the plainer one. Here is every categorical field in the index, its approximate distinct-value count, and how much of the corpus carries nothing in it.

FieldDistinct valuesEmpty or absentShare of corpus
caseType324,577,6802.86%
procedure40521,393,94013.35%
cause (cause of action)~2,13476,213,11647.55%
court~44,6893,817,0512.38%
province~1,23322,323,72513.93%
year8,369,0105.22%

The number that should stop a scoping conversation is the third row. Nearly half the corpus carries no cause of action. Cause of action is the field on which almost every commercially interesting slice depends — construction disputes, private lending, labour, trade secrets. If you plan to sell a product scoped by subject matter, you are working inside the 52% of records that have a label, and that subset is not a random sample of the whole.

The two distinct-value counts flagged with a tilde are the second problem in miniature. There are thirty-four province-level divisions in the PRC and something on the order of a few thousand courts. The index reports 1,233 and 44,689. Neither field is measuring what its name says.

Four vocabularies in one field

The index carries a batch identifier — fifteen acquisitions, ranging from 40.7 million records down to seven thousand. Cross-tabulating procedure against that identifier explains the 405 distinct values immediately. The vocabulary is not a property of the corpus. It is a property of the batch.

VocabularyExample valuesBatchesRecords
Bare integers1, 2, 3, 4one batch39,341,140
Coarse Chinese labelsfirst instance, second instance, retrial, otherthree batches47,611,438
Fine-grained Chinese labelscivil first instance, enforcement execution, civil second instance, non-litigation preservation reviewnine batches68,917,169
Numeric codes0301, 0302, 1001within two batches750,354 (already inside the row above)
Emptyone batch entirely, plus 7,000 rows4,421,931

The last row understates the gap. It counts only the batches that are empty end to end; partial emptiness is spread across the others, and the largest single batch has the field blank on 16,892,448 of its rows. Corpus-wide, 21,393,940 records carry an empty procedure.

These do not nest. "Civil first instance" is narrower than "first instance", which may or may not be what 1 means. One batch of 4,414,931 records has the field populated for exactly zero rows. And the separation is not perfectly clean either: 4,769 records carry an integer procedure while sitting outside the batch that uses integers, and thirty-four rows inside the integer batch carry a Chinese label for "final instance" — a fifth vocabulary, appearing once, in a batch that otherwise contains none.

The 25-million-record question mark

Suppose you want the most basic figure a buyer ever asks for: what proportion of this corpus is first-instance litigation? Add up the values that unambiguously say so.

ValueRecords
civil first instance33,602,755
first instance23,327,533
criminal first instance1,781,808
administrative first instance211,798
Subtotal58,923,894 — 36.76% of the corpus
procedure = 125,110,180
Total if 1 means first instance84,034,074 — 52.43% of the corpus

A fifteen-point swing, twenty-five million records wide, resting on the interpretation of a single digit. The same arithmetic applies on appeal: second-instance records are 4,998,263 without 2 and 9,033,942 with it, which is the difference between an appellate corpus you can build a product on and one you cannot.

We tried to decode it from inside the data, which is the honest thing to attempt and also a useful demonstration of why it does not work. Within the integer batch, cross-tabulating procedure against document type gives:

procedureRecordsComposition
125,105,58766% judgments, 33% rulings, 1% mediation
24,035,65259% judgments, 41% rulings
3558,16986% rulings, 12% judgments
49,641,66495% rulings, plus notices and decisions

This is suggestive. Values 1 and 2 both carry a substantial judgment population, which is what trial levels look like; 3 and 4 are dominated by rulings, which is what review and enforcement look like. The ratio of 1 to 2 is roughly 86:14, which is not far from a plausible trial-to-appeal ratio. Every part of that reasoning is a hypothesis, and a hypothesis is exactly what you must not ship. The batch's own codebook would settle it in one line. From inside the index there is no way to distinguish a correct guess from a confident one, and a wrong guess misclassifies four million appeals.

A field that answers two different questions

The case-type field has only thirty-two distinct values, which makes it look like the well-behaved one. It is not. It is carrying two unrelated taxonomies at once.

Some values name a kind of case: civil, criminal, administrative, enforcement, state compensation. Others name a kind of document: judgment, ruling, mediation agreement, notice, decision. The document-type values account for roughly 39.3 million records, or about 24.53% of the corpus. In other words, for a quarter of the index, the field labelled "case type" does not tell you the type of case at all — and it does not return null, which would at least be visible. It returns a confident, well-formed answer to a question you did not ask.

The same field also shows textbook label drift. Two labels for civil matters exist, one short and one with a "case" suffix. They are almost perfectly disjoint by batch: the short form appears in four batches, the suffixed form in nine, and exactly one batch — the 2024 acquisition — uses both, splitting 283,497 against 4,084,107. Two further batches, together 43.8 million records, use neither, because they are the ones carrying the document-type vocabulary instead.

What drift does not explain

Label drift is a satisfying explanation, which is precisely why it needs testing rather than assuming. In last week's year-by-year census we published an administrative-litigation series we said we did not believe, and named drift as the likely cause. This week we could check it properly. Merging both administrative labels across the whole index gives:

Year20182019202020212022202320242025
Merged records275,680225,306314,895112,2239,3444,78497,55132,751

The drift is real and now measured — the short label dominates 2018 and 2019, the suffixed one dominates 2020 through 2023, both appear in 2024, and 2025 reverts to the short one. But merging them does not restore the series. And the obvious remaining suspect can be ruled out: the batch with the third, document-type vocabulary ends at 2018 — it holds zero records dated 2019 or later, with 83.93% of its volume in 2014–2017 — so it cannot be hiding the administrative cases that went missing in 2021–2023.

So the position moves, but not in the direction we would have preferred. We can now say that vocabulary drift is demonstrably present in this field and demonstrably not the cause of that collapse. The series remains unusable, for a reason we have not identified. We would rather publish that than a tidier sentence.

Keys that are not keys

The last category is smaller in volume and larger in consequence, because it breaks joins rather than counts.

Of the 44,689 distinct court values, 2,721 begin with whitespace or a newline, or contain a literal   HTML entity — raw page markup that survived extraction and became part of a keyword. Between them they cover 28,863 records, about 0.018% of the corpus. That sounds ignorable until you look at what it does. One county court appears as a clean key on 8,268 records and as a whitespace-prefixed key on exactly one more. An exact-match filter on the clean name silently drops the stray. A GROUP BY returns two rows for one court. Multiply by 2,721.

The province field shows the same shape with different debris: single-record keys such as a province name prefixed with plus signs, and — more revealing about where these come from — a handful of values that are fragments of a delimited-file row, quote marks and a UUID included, that landed in the province column when a parser lost its place. The year field has 1,354 records carrying values that cannot be years: three-digit truncations, and a scattering in the 1970s and one in 2027.

The honest weighting is this. None of this moves an aggregate — at these volumes the effect on any percentage on this page is invisible. All of it breaks the operations you would actually build a product on: exact-match filtering, faceted navigation, joins on court identity, script-normalised matching, and any assumption that a distinct-value count tells you how many real entities exist.

The audit to run on any supplier, including us

Everything above is reproducible with six aggregation queries. That makes it a reasonable thing to ask any supplier of Chinese judgment data to hand over before money changes hands.

  1. Ask for the value list with counts, not the schema. A schema tells you a field is a string. The complete list of distinct values with document counts tells you whether it is a controlled vocabulary or a pile of them. Request it for every categorical field, and fold it into the wider coverage-verification protocol rather than treating it as a separate exercise.
  2. Ask for that list broken down by acquisition batch or ingestion source. This is the single highest-yield cut, because vocabulary is almost always a batch property. If the supplier says there is no such field, ask how they would detect drift without one.
  3. Ask for the empty rate per field, per stratum — and distinguish absent from empty-string. A field that is 95% populated overall can be 5% populated in the slice you are buying.
  4. For any coded value, ask for the codebook. If the answer is that the codes came with the source and were never documented, that is a usable answer; you now know to treat those records as an unlabelled stratum rather than silently merging them.
  5. Run the merge test. Identify label variants, merge them, and see whether the anomaly you were chasing disappears. When it does not, resist the explanation you liked.
  6. Diff two deliveries. Vocabulary drift enters through new batches. A field that was clean at signature can acquire a fifth vocabulary at the next refresh, which is one of the things a published change log exists to surface.

What this census cannot tell you

The short version

A large Chinese judgment corpus is an accretion, not a build. Fifteen acquisitions over a decade, from a public record whose own export conventions changed repeatedly, produce a metadata layer where the same concept has four spellings, where a quarter of one field answers a different question than its name implies, where nearly half the corpus has no cause of action, and where the most basic structural statistic you can state about the data moves by twenty-five million records depending on how you read one digit.

The reason to publish this rather than quietly normalise it is that the normalisation decisions are the interesting part, and they belong to the buyer as much as the supplier — which is why we expose the field structure before anything is signed. Whoever decides that 1 means first instance is making a modelling choice with fifteen points of headline coverage riding on it. That decision should be documented, argued and owned — not inherited from whoever wrote the ingestion script.

We are the party selling the data, and most of this page argues against us. That is deliberate. A supplier who cannot produce these tables has not proved their corpus is clean; they have proved they have not looked.

Frequently asked questions

Why does the same field in a Chinese judgment corpus contain several different vocabularies?

Because a corpus of this size is an accretion rather than a build. Ours was assembled from fifteen separate acquisitions drawn from a public record whose own export conventions changed repeatedly over a decade, and the labelling convention travels with the batch. In our index the procedure field holds bare integers in one batch of 39,341,140 records, coarse Chinese labels in three more, fine-grained Chinese labels in nine, four-digit numeric codes inside two of those, and nothing at all in one batch of 4,414,931 records. The values do not nest, so they cannot simply be merged. The practical consequence is that a distinct-value count on a categorical field tells you how many labelling conventions the supplier has ingested, not how many real categories exist.

What should I ask a Chinese case law supplier about metadata quality?

Ask for the complete list of distinct values with document counts for every categorical field, broken down by acquisition batch or ingestion source. A schema document will tell you a field is a string; only the value list tells you whether it is a controlled vocabulary or several of them stacked on top of each other. Then ask for the empty rate per field within the specific stratum you intend to buy rather than across the whole corpus, and insist on the distinction between a field that is absent and one that holds an empty string. For any coded value, ask for the codebook; if it was never documented, that is a usable answer, because you now know to treat those records as an unlabelled stratum instead of silently merging them.

How much of a PRC judgment corpus actually has a usable cause of action?

In our index, 76,213,116 records out of 160,291,678 carry an empty cause-of-action field, which is 47.55% of the corpus. That matters more than the headline size, because cause of action is the field on which almost every commercially interesting slice depends, from construction disputes to private lending to labour matters. If your product is scoped by subject matter, you are working inside the labelled remainder, and there is no reason to assume that remainder is a random sample of the whole. The correct question to a supplier is not how many records they hold but how many are labelled in the dimension your product actually filters on.

Do whitespace and HTML entities inside a court field actually matter?

They barely move an aggregate and they reliably break a join, which is the opposite of how most teams triage them. Of the 44,689 distinct court values in our index, 2,721 begin with whitespace or a newline or contain a literal non-breaking-space entity left over from page extraction, together covering 28,863 records, about 0.018% of the corpus. One county court appears under a clean key on 8,268 records and under a whitespace-prefixed key on one more. Any percentage you compute is unaffected; any exact-match filter, faceted count or join on court identity silently produces the wrong answer. Volume is the wrong lens for this class of defect.

Is a distinct-value count a good measure of how many courts or provinces a corpus covers?

No, and treating it as one is a common way to overstate coverage. There are thirty-four province-level divisions in the PRC; our province field reports roughly 1,233 distinct values, and its rare tail includes fragments of delimited-file rows, quote marks and identifiers included, that landed in the column when a parser lost its place. The court field reports roughly 44,689 values against a court system numbering in the low thousands. We have characterised 2,721 of those court keys as whitespace or entity variants and have not sorted the remainder, some of which are legitimate dispatched tribunals or historical designations. The reliable measure is the count of distinct values that survive normalisation, and a supplier who has never run that normalisation cannot tell you what it is.

Ask for the value list before you ask for the record count.

SinoVerdict licenses PRC judgment data to teams building legal AI — bulk delivery, a REST API and an MCP endpoint over a 160M+ record corpus, English-indexed, with the field structure and its known gaps documented before anything is signed. Send us the fields your product filters on and we will run the value-list, batch and empty-rate breakdowns above against the exact slice you are considering, including the parts that come back messy. Write to chenjiaxin@wenshucha.com or use the form.

Request trial access