Back to Feed
article 3m read

Zero products matched because the size field held the whole label

One vendor's slots matched nothing, so every slot got the same flat order suggestion. The stored size was a full label descriptor, the catalog left out the default size, and my existing default rule could never fire. Now the matcher pulls sizes out of the label, guesses the default only when nothing contradicts it, and prunes links a re-run no longer matches.

Article DepthPractice

Flow

How a product gets into a slot now

  1. 11. Pull sizes from the label

    Keep only the pieces of the slot label that read as sizes.

  2. 22. Compare

    Any size shared with the product is a match.

  3. 33. Fall back

    If nothing is shared, run the old checks.

  4. 44. Guess the default, narrowly

    One default size in the label and no size on the product means the product gets the default.

  5. 55. Stated sizes win

    A product that names a size is judged on that size.

  6. 66. Clear old links

    Real runs delete links the new run did not match. Dry runs delete nothing and report zero.

Nothing matched when the ordering system checked one vendor's catalog against every slot in its plan: zero products. Not a few. Zero.

Those matches are how the system estimates demand. For each slot it finds the same products in an outside store catalog, and is meant to size the order from how fast they sell. With no matches it had nothing to go on, so it fell back to a flat floor and gave every slot the same number. It looked like an order, but it was a shrug with numbers in it.

Two fields that could never agree

My plan stored size badly. Each slot's size field held the whole label: product family, size, price and case count, all in one string. My size parser is strict and only reads a number with a known unit. As far as I can tell, the whole label didn't read as a size, so the check was left comparing raw text, and a long label never equals a clean size.

The catalog often had no size at all. Lots of products came with no size and no weight, because the feed only names the other sizes in the title and leaves the default size out.

So the size was unreadable on my side and missing on theirs, and every product got rejected.

A default rule that could never fire

I already had a rule for the missing default: if a slot wanted the default size and a product gave no size, the product could take it. But the rule checked whether the slot's whole size field equalled the default size. A long label never does, so the rule never fired.

Reading the size out of the label

The change doesn't clean the stored data by hand, and it doesn't switch to fuzzy matching. The check now splits the slot's label into pieces, keeps the pieces that read as sizes, and compares those with the product's sizes. Any shared size is a match. If there isn't one, the old checks still run, so slots with a clean size should behave about the same as before.

The parser also learned to read a pack unit.

The narrow guess

The default guess only fires when the label holds exactly one size, that size is the default, and the product states no size at all. A product that states a size is judged on that size. When the guess fires, the product gets the clean size, not the whole label.

Three tests, two of them refusals

One test puts a product with no size in the default slot. Another sends a product with the larger size to the larger slot and keeps it out of the default one. The third keeps a product with a blended type out of a single-type slot. They check which products matched, not how many.

Stale links

The sync used to only add links between slots and products, so old links stayed around and kept feeding demand. Now it deletes any link that the new run didn't match, and a real run reports how many it removed. A dry run skips the deletes, so it always reports zero, which means I can't use it to see what a real run would throw away. I'd like that number before the deletes, not after.

Keep reading

Pick up a connected idea or branch into a nearby one.

5 paths forward